Merge branch 'dash-bart-random' into ble-message
This commit is contained in:
commit
5ca622a923
46 changed files with 653 additions and 851 deletions
|
@ -3,6 +3,9 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManager
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManager
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.GetVersionCommand
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.GetVersionCommand.Companion.DEFAULT_UNIQUE_ID
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ActivationProgress
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertConfiguration
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertSlot
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertSlot
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BasalProgram
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BasalProgram
|
||||||
|
@ -19,10 +22,38 @@ class OmnipodDashManagerImpl @Inject constructor(
|
||||||
private val bleManager: OmnipodDashBleManager
|
private val bleManager: OmnipodDashBleManager
|
||||||
) : OmnipodDashManager {
|
) : OmnipodDashManager {
|
||||||
|
|
||||||
override fun activatePodPart1(): Observable<PodEvent> {
|
private val observePodReadyForActivationPart1: Observable<PodEvent>
|
||||||
// TODO
|
get() {
|
||||||
|
if (podStateManager.activationProgress.isBefore(ActivationProgress.PHASE_1_COMPLETED)) {
|
||||||
return Observable.empty()
|
return Observable.empty()
|
||||||
}
|
}
|
||||||
|
return Observable.error(IllegalStateException("Pod is in an incorrect state"))
|
||||||
|
}
|
||||||
|
|
||||||
|
private val observeConnectToPod: Observable<PodEvent>
|
||||||
|
get() {
|
||||||
|
return Observable.defer {
|
||||||
|
bleManager.connect()
|
||||||
|
Observable.just(PodEvent.Connected(0)) // TODO should be returned in BleManager
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun activatePodPart1(): Observable<PodEvent> {
|
||||||
|
val command = GetVersionCommand.Builder() //
|
||||||
|
.setSequenceNumber(podStateManager.messageSequenceNumber) //
|
||||||
|
.setUniqueId(DEFAULT_UNIQUE_ID) //
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return Observable.concat(
|
||||||
|
observePodReadyForActivationPart1,
|
||||||
|
observeConnectToPod,
|
||||||
|
Observable.defer {
|
||||||
|
bleManager.sendCommand(command)
|
||||||
|
Observable.just(PodEvent.CommandSent(command)) // TODO should be returned in BleManager
|
||||||
|
}
|
||||||
|
// ... Send more commands
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun activatePodPart2(): Observable<PodEvent> {
|
override fun activatePodPart2(): Observable<PodEvent> {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
|
@ -110,7 +110,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)
|
||||||
|
@ -128,7 +128,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)
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event
|
||||||
|
|
||||||
class PodEvent(
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command
|
||||||
val type: PodEventType,
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.Response
|
||||||
val data: Any?
|
|
||||||
)
|
sealed class PodEvent {
|
||||||
|
|
||||||
|
object Scanning : PodEvent()
|
||||||
|
object Pairing : PodEvent()
|
||||||
|
object Connecting : PodEvent()
|
||||||
|
class Connected(val uniqueId: Int) : PodEvent()
|
||||||
|
class CommandSending(val command: Command) : PodEvent()
|
||||||
|
class CommandSent(val command: Command) : PodEvent()
|
||||||
|
class ResponseReceived(val response: Response) : PodEvent()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event
|
|
||||||
|
|
||||||
enum class PodEventType {
|
|
||||||
SCANNING,
|
|
||||||
PAIRING,
|
|
||||||
CONNECTING,
|
|
||||||
CONNECTED,
|
|
||||||
COMMAND_SENDING,
|
|
||||||
COMMAND_SENT,
|
|
||||||
RESPONSE_RECEIVED,
|
|
||||||
// ...
|
|
||||||
}
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -7,11 +7,11 @@ 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,
|
||||||
alertConfigurations: List<AlertConfiguration>?,
|
alertConfigurations: List<AlertConfiguration>,
|
||||||
nonce: Int
|
nonce: Int
|
||||||
) : NonceEnabledCommand(CommandType.PROGRAM_ALERTS, uniqueId, sequenceNumber, multiCommandFlag, nonce) {
|
) : NonceEnabledCommand(CommandType.PROGRAM_ALERTS, uniqueId, sequenceNumber, multiCommandFlag, nonce) {
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ class ProgramAlertsCommand internal constructor(
|
||||||
class Builder : NonceEnabledCommandBuilder<Builder, ProgramAlertsCommand>() {
|
class Builder : NonceEnabledCommandBuilder<Builder, ProgramAlertsCommand>() {
|
||||||
|
|
||||||
private var alertConfigurations: List<AlertConfiguration>? = null
|
private var alertConfigurations: List<AlertConfiguration>? = null
|
||||||
|
|
||||||
fun setAlertConfigurations(alertConfigurations: List<AlertConfiguration>?): Builder {
|
fun setAlertConfigurations(alertConfigurations: List<AlertConfiguration>?): Builder {
|
||||||
this.alertConfigurations = alertConfigurations
|
this.alertConfigurations = alertConfigurations
|
||||||
return this
|
return this
|
||||||
|
@ -59,7 +60,7 @@ class ProgramAlertsCommand internal constructor(
|
||||||
|
|
||||||
override fun buildCommand(): ProgramAlertsCommand {
|
override fun buildCommand(): ProgramAlertsCommand {
|
||||||
requireNotNull(alertConfigurations) { "alertConfigurations can not be null" } // !!?
|
requireNotNull(alertConfigurations) { "alertConfigurations can not be null" } // !!?
|
||||||
return ProgramAlertsCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, alertConfigurations, nonce!!) // TODO this might crash if not all are set
|
return ProgramAlertsCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, alertConfigurations!!, nonce!!) // TODO this might crash if not all are set
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -76,6 +76,7 @@ class ProgramBasalCommand internal constructor(
|
||||||
private var basalProgram: BasalProgram? = null
|
private var basalProgram: BasalProgram? = null
|
||||||
private var programReminder: ProgramReminder? = null
|
private var programReminder: ProgramReminder? = null
|
||||||
private var currentTime: Date? = null
|
private var currentTime: Date? = null
|
||||||
|
|
||||||
fun setBasalProgram(basalProgram: BasalProgram?): Builder {
|
fun setBasalProgram(basalProgram: BasalProgram?): Builder {
|
||||||
this.basalProgram = basalProgram
|
this.basalProgram = basalProgram
|
||||||
return this
|
return this
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -57,6 +57,7 @@ class ProgramBolusCommand internal constructor(
|
||||||
private var numberOfUnits: Double? = null
|
private var numberOfUnits: Double? = null
|
||||||
private var delayBetweenPulsesInEighthSeconds: Byte? = null
|
private var delayBetweenPulsesInEighthSeconds: Byte? = null
|
||||||
private var programReminder: ProgramReminder? = null
|
private var programReminder: ProgramReminder? = null
|
||||||
|
|
||||||
fun setNumberOfUnits(numberOfUnits: Double): Builder {
|
fun setNumberOfUnits(numberOfUnits: Double): Builder {
|
||||||
require(numberOfUnits > 0.0) { "Number of units should be greater than zero" }
|
require(numberOfUnits > 0.0) { "Number of units should be greater than zero" }
|
||||||
require((numberOfUnits * 1000).toInt() % 50 == 0) { "Number of units must be dividable by 0.05" }
|
require((numberOfUnits * 1000).toInt() % 50 == 0) { "Number of units must be dividable by 0.05" }
|
||||||
|
@ -78,6 +79,7 @@ class ProgramBolusCommand internal constructor(
|
||||||
requireNotNull(numberOfUnits) { "numberOfUnits can not be null" }
|
requireNotNull(numberOfUnits) { "numberOfUnits can not be null" }
|
||||||
requireNotNull(delayBetweenPulsesInEighthSeconds) { "delayBetweenPulsesInEighthSeconds can not be null" }
|
requireNotNull(delayBetweenPulsesInEighthSeconds) { "delayBetweenPulsesInEighthSeconds can not be null" }
|
||||||
requireNotNull(programReminder) { "programReminder can not be null" }
|
requireNotNull(programReminder) { "programReminder can not be null" }
|
||||||
|
|
||||||
val numberOfPulses = Math.round(numberOfUnits!! * 20).toShort()
|
val numberOfPulses = Math.round(numberOfUnits!! * 20).toShort()
|
||||||
val byte10And11 = (numberOfPulses * delayBetweenPulsesInEighthSeconds!!).toShort()
|
val byte10And11 = (numberOfPulses * delayBetweenPulsesInEighthSeconds!!).toShort()
|
||||||
val interlockCommand = ProgramInsulinCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, nonce!!, listOf(BolusShortInsulinProgramElement(numberOfPulses)), calculateChecksum(0x01.toByte(), byte10And11, numberOfPulses),
|
val interlockCommand = ProgramInsulinCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, nonce!!, listOf(BolusShortInsulinProgramElement(numberOfPulses)), calculateChecksum(0x01.toByte(), byte10And11, numberOfPulses),
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -34,14 +34,6 @@ class ProgramInsulinCommand(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateChecksum(bytes: ByteArray): Short {
|
|
||||||
var sum: Short = 0
|
|
||||||
for (b in bytes) {
|
|
||||||
sum = ((b.toInt() and 0xff) + sum).toShort() // TODO Adrian: int conversion ok?
|
|
||||||
}
|
|
||||||
return sum
|
|
||||||
}
|
|
||||||
|
|
||||||
override val encoded: ByteArray
|
override val encoded: ByteArray
|
||||||
get() {
|
get() {
|
||||||
val buffer = ByteBuffer.allocate(getLength().toInt()) //
|
val buffer = ByteBuffer.allocate(getLength().toInt()) //
|
||||||
|
|
|
@ -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,16 +20,18 @@ 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>() {
|
||||||
|
|
||||||
private var programReminder: ProgramReminder? = null
|
private var programReminder: ProgramReminder? = null
|
||||||
private var rateInUnitsPerHour: Double? = null
|
private var rateInUnitsPerHour: Double? = null
|
||||||
private var durationInMinutes: Short? = null
|
private var durationInMinutes: Short? = null
|
||||||
|
|
||||||
fun setProgramReminder(programReminder: ProgramReminder?): Builder {
|
fun setProgramReminder(programReminder: ProgramReminder?): Builder {
|
||||||
this.programReminder = programReminder
|
this.programReminder = programReminder
|
||||||
return this
|
return this
|
||||||
|
@ -42,6 +44,7 @@ class ProgramTempBasalCommand protected constructor(
|
||||||
|
|
||||||
fun setDurationInMinutes(durationInMinutes: Short): Builder {
|
fun setDurationInMinutes(durationInMinutes: Short): Builder {
|
||||||
require(durationInMinutes % 30 == 0) { "durationInMinutes must be dividable by 30" }
|
require(durationInMinutes % 30 == 0) { "durationInMinutes must be dividable by 30" }
|
||||||
|
|
||||||
this.durationInMinutes = durationInMinutes
|
this.durationInMinutes = durationInMinutes
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
@ -50,22 +53,19 @@ class ProgramTempBasalCommand protected constructor(
|
||||||
requireNotNull(programReminder) { "programReminder can not be null" }
|
requireNotNull(programReminder) { "programReminder can not be null" }
|
||||||
requireNotNull(rateInUnitsPerHour) { "rateInUnitsPerHour can not be null" }
|
requireNotNull(rateInUnitsPerHour) { "rateInUnitsPerHour can not be null" }
|
||||||
requireNotNull(durationInMinutes) { "durationInMinutes can not be null" }
|
requireNotNull(durationInMinutes) { "durationInMinutes can not be null" }
|
||||||
|
|
||||||
val durationInSlots = (durationInMinutes!! / 30).toByte()
|
val durationInSlots = (durationInMinutes!! / 30).toByte()
|
||||||
val pulsesPerSlot = ProgramTempBasalUtil.mapTempBasalToPulsesPerSlot(durationInSlots, rateInUnitsPerHour!!)
|
val pulsesPerSlot = ProgramTempBasalUtil.mapTempBasalToPulsesPerSlot(durationInSlots, rateInUnitsPerHour!!)
|
||||||
val tenthPulsesPerSlot = ProgramTempBasalUtil.mapTempBasalToTenthPulsesPerSlot(durationInSlots.toInt(), rateInUnitsPerHour!!)
|
val tenthPulsesPerSlot = ProgramTempBasalUtil.mapTempBasalToTenthPulsesPerSlot(durationInSlots.toInt(), rateInUnitsPerHour!!)
|
||||||
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 +90,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) //
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -45,6 +45,7 @@ class SetUniqueIdCommand internal constructor(
|
||||||
private var lotNumber: Int? = null
|
private var lotNumber: Int? = null
|
||||||
private var podSequenceNumber: Int? = null
|
private var podSequenceNumber: Int? = null
|
||||||
private var initializationTime: Date? = null
|
private var initializationTime: Date? = null
|
||||||
|
|
||||||
fun setLotNumber(lotNumber: Int): Builder {
|
fun setLotNumber(lotNumber: Int): Builder {
|
||||||
this.lotNumber = lotNumber
|
this.lotNumber = lotNumber
|
||||||
return this
|
return this
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -63,6 +63,7 @@ class SilenceAlertsCommand internal constructor(
|
||||||
private var silenceSuspendInProgressAlert = false
|
private var silenceSuspendInProgressAlert = false
|
||||||
private var silenceSuspendEndedAlert = false
|
private var silenceSuspendEndedAlert = false
|
||||||
private var silencePodExpirationAlert = false
|
private var silencePodExpirationAlert = false
|
||||||
|
|
||||||
fun setSilenceAutoOffAlert(silenceAutoOffAlert: Boolean): Builder {
|
fun setSilenceAutoOffAlert(silenceAutoOffAlert: Boolean): Builder {
|
||||||
this.silenceAutoOffAlert = silenceAutoOffAlert
|
this.silenceAutoOffAlert = silenceAutoOffAlert
|
||||||
return this
|
return this
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ class StopDeliveryCommand internal constructor(
|
||||||
|
|
||||||
private var deliveryType: DeliveryType? = null
|
private var deliveryType: DeliveryType? = null
|
||||||
private var beepType: BeepType? = BeepType.LONG_SINGLE_BEEP
|
private var beepType: BeepType? = BeepType.LONG_SINGLE_BEEP
|
||||||
|
|
||||||
fun setDeliveryType(deliveryType: DeliveryType?): Builder {
|
fun setDeliveryType(deliveryType: DeliveryType?): Builder {
|
||||||
this.deliveryType = deliveryType
|
this.deliveryType = deliveryType
|
||||||
return this
|
return this
|
||||||
|
@ -70,6 +71,7 @@ class StopDeliveryCommand internal constructor(
|
||||||
override fun buildCommand(): StopDeliveryCommand {
|
override fun buildCommand(): StopDeliveryCommand {
|
||||||
requireNotNull(deliveryType) { "deliveryType can not be null" }
|
requireNotNull(deliveryType) { "deliveryType can not be null" }
|
||||||
requireNotNull(beepType) { "beepType can not be null" }
|
requireNotNull(beepType) { "beepType can not be null" }
|
||||||
|
|
||||||
return StopDeliveryCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, deliveryType!!, beepType!!, nonce!!)
|
return StopDeliveryCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, deliveryType!!, beepType!!, nonce!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()),
|
||||||
|
|
|
@ -2,11 +2,13 @@ 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
|
||||||
protected var sequenceNumber: Short? = null
|
protected var sequenceNumber: Short? = null
|
||||||
protected var multiCommandFlag = false
|
protected var multiCommandFlag = false
|
||||||
|
|
||||||
override fun build(): R {
|
override fun build(): R {
|
||||||
requireNotNull(uniqueId) { "uniqueId can not be null" }
|
requireNotNull(uniqueId) { "uniqueId can not be null" }
|
||||||
requireNotNull(sequenceNumber) { "sequenceNumber can not be null" }
|
requireNotNull(sequenceNumber) { "sequenceNumber can not be null" }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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()) //
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@ class BasalProgram(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val segments: MutableList<Segment> = segments.toMutableList()
|
val segments: MutableList<Segment> = segments.toMutableList()
|
||||||
get() = Collections.unmodifiableList(field) // TODO Adrian: moved method here
|
get() = Collections.unmodifiableList(field)
|
||||||
|
|
||||||
fun addSegment(segment: Segment) {
|
fun addSegment(segment: Segment) {
|
||||||
segments.add(segment)
|
segments.add(segment)
|
||||||
|
@ -19,7 +19,11 @@ class BasalProgram(
|
||||||
|
|
||||||
fun rateAt(date: Date): Double = 0.0 // TODO
|
fun rateAt(date: Date): Double = 0.0 // TODO
|
||||||
|
|
||||||
class Segment(val startSlotIndex: Short, val endSlotIndex: Short, val basalRateInHundredthUnitsPerHour: Int) {
|
class Segment(
|
||||||
|
val startSlotIndex: Short,
|
||||||
|
val endSlotIndex: Short,
|
||||||
|
val basalRateInHundredthUnitsPerHour: Int
|
||||||
|
) {
|
||||||
|
|
||||||
fun getPulsesPerHour(): Short {
|
fun getPulsesPerHour(): Short {
|
||||||
return (basalRateInHundredthUnitsPerHour * PULSES_PER_UNIT / 100).toShort()
|
return (basalRateInHundredthUnitsPerHour * PULSES_PER_UNIT / 100).toShort()
|
||||||
|
@ -37,6 +41,26 @@ class BasalProgram(
|
||||||
'}'
|
'}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as Segment
|
||||||
|
|
||||||
|
if (startSlotIndex != other.startSlotIndex) return false
|
||||||
|
if (endSlotIndex != other.endSlotIndex) return false
|
||||||
|
if (basalRateInHundredthUnitsPerHour != other.basalRateInHundredthUnitsPerHour) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result: Int = startSlotIndex.toInt()
|
||||||
|
result = 31 * result + endSlotIndex
|
||||||
|
result = 31 * result + basalRateInHundredthUnitsPerHour
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val PULSES_PER_UNIT: Byte = 20
|
private const val PULSES_PER_UNIT: Byte = 20
|
||||||
|
@ -48,4 +72,19 @@ class BasalProgram(
|
||||||
"segments=" + segments +
|
"segments=" + segments +
|
||||||
'}'
|
'}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as BasalProgram
|
||||||
|
|
||||||
|
if (segments != other.segments) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return segments.hashCode()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,10 +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 BeepType( // Used in stop delivery command
|
enum class BeepType(val value: Byte) {
|
||||||
val value: Byte
|
|
||||||
) {
|
|
||||||
|
|
||||||
SILENT(0x00.toByte()),
|
SILENT(0x00.toByte()),
|
||||||
FOUR_TIMES_BIP_BEEP(0x02.toByte()), // Used in low reservoir alert, user expiration alert, expiration alert, imminent expiration alert, lump of coal alert
|
FOUR_TIMES_BIP_BEEP(0x02.toByte()), // Used in low reservoir alert, user expiration alert, expiration alert, imminent expiration alert, lump of coal alert
|
||||||
LONG_SINGLE_BEEP(0x06.toByte());
|
LONG_SINGLE_BEEP(0x06.toByte()); // Used in stop delivery command
|
||||||
}
|
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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
|
||||||
}
|
}
|
|
@ -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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,107 +2,32 @@ 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(
|
||||||
encoded: ByteArray
|
encoded: ByteArray
|
||||||
) : ActivationResponseBase(ActivationResponseType.SET_UNIQUE_ID_RESPONSE, encoded) {
|
) : ActivationResponseBase(ActivationResponseType.SET_UNIQUE_ID_RESPONSE, encoded) {
|
||||||
|
|
||||||
private val messageType: Byte // TODO directly assign here
|
val messageType: Byte = encoded[0]
|
||||||
private val messageLength: Short
|
val messageLength: Short = (encoded[1].toInt() and 0xff).toShort()
|
||||||
private val pulseVolumeInTenThousandthMicroLiter: Short
|
val pulseVolumeInTenThousandthMicroLiter: Short = ByteBuffer.wrap(byteArrayOf(encoded[2], encoded[3])).short
|
||||||
private val pumpRate: Short
|
val pumpRate: Short = (encoded[4].toInt() and 0xff).toShort()
|
||||||
private val primePumpRate: Short
|
val primePumpRate: Short = (encoded[5].toInt() and 0xff).toShort()
|
||||||
private val numberOfEngagingClutchDrivePulses: Short
|
val numberOfEngagingClutchDrivePulses: Short = (encoded[6].toInt() and 0xff).toShort()
|
||||||
private val numberOfPrimePulses: Short
|
val numberOfPrimePulses: Short = (encoded[7].toInt() and 0xff).toShort()
|
||||||
private val podExpirationTimeInHours: Short
|
val podExpirationTimeInHours: Short = (encoded[8].toInt() and 0xff).toShort()
|
||||||
private val firmwareVersionMajor: Short
|
val firmwareVersionMajor: Short = (encoded[9].toInt() and 0xff).toShort()
|
||||||
private val firmwareVersionMinor: Short
|
val firmwareVersionMinor: Short = (encoded[10].toInt() and 0xff).toShort()
|
||||||
private val firmwareVersionInterim: Short
|
val firmwareVersionInterim: Short = (encoded[11].toInt() and 0xff).toShort()
|
||||||
private val bleVersionMajor: Short
|
val bleVersionMajor: Short = (encoded[12].toInt() and 0xff).toShort()
|
||||||
private val bleVersionMinor: Short
|
val bleVersionMinor: Short = (encoded[13].toInt() and 0xff).toShort()
|
||||||
private val bleVersionInterim: Short
|
val bleVersionInterim: Short = (encoded[14].toInt() and 0xff).toShort()
|
||||||
private val productId: Short
|
val productId: Short = (encoded[15].toInt() and 0xff).toShort()
|
||||||
private val podStatus: PodStatus
|
val podStatus: PodStatus = byValue(encoded[16], PodStatus.UNKNOWN)
|
||||||
private val lotNumber: Long
|
val lotNumber: Long = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[17], encoded[18], encoded[19], encoded[20])).long
|
||||||
private val podSequenceNumber: Long
|
val podSequenceNumber: Long = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[21], encoded[22], encoded[23], encoded[24])).long
|
||||||
private val uniqueIdReceivedInCommand: Long
|
val uniqueIdReceivedInCommand: Long = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[25], encoded[26], encoded[27], encoded[28])).long
|
||||||
|
|
||||||
fun getMessageType(): Byte {
|
|
||||||
return messageType
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMessageLength(): Short { // TODO value getters
|
|
||||||
return messageLength
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPulseVolumeInTenThousandthMicroLiter(): Short {
|
|
||||||
return pulseVolumeInTenThousandthMicroLiter
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getDeliveryRate(): Short {
|
|
||||||
return pumpRate
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPrimeRate(): Short {
|
|
||||||
return primePumpRate
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getNumberOfEngagingClutchDrivePulses(): Short {
|
|
||||||
return numberOfEngagingClutchDrivePulses
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getNumberOfPrimePulses(): Short {
|
|
||||||
return numberOfPrimePulses
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPodExpirationTimeInHours(): Short {
|
|
||||||
return podExpirationTimeInHours
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFirmwareVersionMajor(): Short {
|
|
||||||
return firmwareVersionMajor
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFirmwareVersionMinor(): Short {
|
|
||||||
return firmwareVersionMinor
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFirmwareVersionInterim(): Short {
|
|
||||||
return firmwareVersionInterim
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBleVersionMajor(): Short {
|
|
||||||
return bleVersionMajor
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBleVersionMinor(): Short {
|
|
||||||
return bleVersionMinor
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBleVersionInterim(): Short {
|
|
||||||
return bleVersionInterim
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getProductId(): Short {
|
|
||||||
return productId
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPodStatus(): PodStatus {
|
|
||||||
return podStatus
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLotNumber(): Long {
|
|
||||||
return lotNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPodSequenceNumber(): Long {
|
|
||||||
return podSequenceNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getUniqueIdReceivedInCommand(): Long {
|
|
||||||
return uniqueIdReceivedInCommand
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "SetUniqueIdResponse{" +
|
return "SetUniqueIdResponse{" +
|
||||||
|
@ -131,25 +56,4 @@ class SetUniqueIdResponse(
|
||||||
'}'
|
'}'
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
messageType = encoded[0]
|
|
||||||
messageLength = (encoded[1].toInt() and 0xff).toShort()
|
|
||||||
pulseVolumeInTenThousandthMicroLiter = ByteBuffer.wrap(byteArrayOf(encoded[2], encoded[3])).short
|
|
||||||
pumpRate = (encoded[4].toInt() and 0xff).toShort()
|
|
||||||
primePumpRate = (encoded[5].toInt() and 0xff).toShort()
|
|
||||||
numberOfEngagingClutchDrivePulses = (encoded[6].toInt() and 0xff).toShort()
|
|
||||||
numberOfPrimePulses = (encoded[7].toInt() and 0xff).toShort()
|
|
||||||
podExpirationTimeInHours = (encoded[8].toInt() and 0xff).toShort()
|
|
||||||
firmwareVersionMajor = (encoded[9].toInt() and 0xff).toShort()
|
|
||||||
firmwareVersionMinor = (encoded[10].toInt() and 0xff).toShort()
|
|
||||||
firmwareVersionInterim = (encoded[11].toInt() and 0xff).toShort()
|
|
||||||
bleVersionMajor = (encoded[12].toInt() and 0xff).toShort()
|
|
||||||
bleVersionMinor = (encoded[13].toInt() and 0xff).toShort()
|
|
||||||
bleVersionInterim = (encoded[14].toInt() and 0xff).toShort()
|
|
||||||
productId = (encoded[15].toInt() and 0xff).toShort()
|
|
||||||
podStatus = PodStatus.byValue(encoded[16])
|
|
||||||
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
|
|
||||||
uniqueIdReceivedInCommand = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[25], encoded[26], encoded[27], encoded[28])).long
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
@ -10,81 +11,21 @@ class VersionResponse(
|
||||||
encoded: ByteArray
|
encoded: ByteArray
|
||||||
) : ActivationResponseBase(ActivationResponseType.GET_VERSION_RESPONSE, encoded) {
|
) : ActivationResponseBase(ActivationResponseType.GET_VERSION_RESPONSE, encoded) {
|
||||||
|
|
||||||
private val messageType: Byte = encoded[0]
|
val messageType: Byte = encoded[0]
|
||||||
private val messageLength: Short = (encoded[1].toInt() and 0xff).toShort()
|
val messageLength: Short = (encoded[1].toInt() and 0xff).toShort()
|
||||||
private val firmwareVersionMajor: Short = (encoded[2].toInt() and 0xff).toShort()
|
val firmwareVersionMajor: Short = (encoded[2].toInt() and 0xff).toShort()
|
||||||
private val firmwareVersionMinor: Short = (encoded[3].toInt() and 0xff).toShort()
|
val firmwareVersionMinor: Short = (encoded[3].toInt() and 0xff).toShort()
|
||||||
private val firmwareVersionInterim: Short = (encoded[4].toInt() and 0xff).toShort()
|
val firmwareVersionInterim: Short = (encoded[4].toInt() and 0xff).toShort()
|
||||||
private val bleVersionMajor: Short = (encoded[5].toInt() and 0xff).toShort()
|
val bleVersionMajor: Short = (encoded[5].toInt() and 0xff).toShort()
|
||||||
private val bleVersionMinor: Short = (encoded[6].toInt() and 0xff).toShort()
|
val bleVersionMinor: Short = (encoded[6].toInt() and 0xff).toShort()
|
||||||
private val bleVersionInterim: Short = (encoded[7].toInt() and 0xff).toShort()
|
val bleVersionInterim: Short = (encoded[7].toInt() and 0xff).toShort()
|
||||||
private val productId: Short = (encoded[8].toInt() and 0xff).toShort()
|
val productId: Short = (encoded[8].toInt() and 0xff).toShort()
|
||||||
private val podStatus: PodStatus = PodStatus.byValue((encoded[9] and 0xf))
|
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
|
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
|
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)
|
val rssi: Byte = (encoded[18] and 0x3f)
|
||||||
private val receiverLowerGain: Byte = ((encoded[18].toInt() shr 6 and 0x03).toByte())
|
val receiverLowerGain: Byte = ((encoded[18].toInt() shr 6 and 0x03).toByte())
|
||||||
private val uniqueIdReceivedInCommand: Long = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[19], encoded[20], encoded[21], encoded[22])).long
|
val uniqueIdReceivedInCommand: Long = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[19], encoded[20], encoded[21], encoded[22])).long
|
||||||
|
|
||||||
fun getMessageType(): Byte {
|
|
||||||
return messageType
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMessageLength(): Short {
|
|
||||||
return messageLength
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFirmwareVersionMajor(): Short {
|
|
||||||
return firmwareVersionMajor
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFirmwareVersionMinor(): Short {
|
|
||||||
return firmwareVersionMinor
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFirmwareVersionInterim(): Short {
|
|
||||||
return firmwareVersionInterim
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBleVersionMajor(): Short {
|
|
||||||
return bleVersionMajor
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBleVersionMinor(): Short {
|
|
||||||
return bleVersionMinor
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBleVersionInterim(): Short {
|
|
||||||
return bleVersionInterim
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getProductId(): Short {
|
|
||||||
return productId
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPodStatus(): PodStatus {
|
|
||||||
return podStatus
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLotNumber(): Long {
|
|
||||||
return lotNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPodSequenceNumber(): Long {
|
|
||||||
return podSequenceNumber
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getRssi(): Byte {
|
|
||||||
return rssi
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getReceiverLowerGain(): Byte {
|
|
||||||
return receiverLowerGain
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getUniqueIdReceivedInCommand(): Long {
|
|
||||||
return uniqueIdReceivedInCommand
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "VersionResponse{" +
|
return "VersionResponse{" +
|
||||||
|
|
|
@ -34,14 +34,20 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
store()
|
store()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val isUniqueIdSet: Boolean = activationProgress.isAtLeast(ActivationProgress.SET_UNIQUE_ID)
|
// TODO: dynamic get() fun instead of assignment
|
||||||
|
|
||||||
override val isActivationCompleted: Boolean = activationProgress == ActivationProgress.COMPLETED
|
override val isUniqueIdSet: Boolean
|
||||||
|
get() = activationProgress.isAtLeast(ActivationProgress.SET_UNIQUE_ID)
|
||||||
|
|
||||||
override val isSuspended: Boolean = podState.deliveryStatus?.equals(DeliveryStatus.SUSPENDED)
|
override val isActivationCompleted: Boolean
|
||||||
|
get() = activationProgress == ActivationProgress.COMPLETED
|
||||||
|
|
||||||
|
override val isSuspended: Boolean
|
||||||
|
get() = podState.deliveryStatus?.equals(DeliveryStatus.SUSPENDED)
|
||||||
?: true
|
?: true
|
||||||
|
|
||||||
override val isPodRunning: Boolean = podState.podStatus?.isRunning() ?: false
|
override val isPodRunning: Boolean
|
||||||
|
get() = podState.podStatus?.isRunning() ?: false
|
||||||
|
|
||||||
override var lastConnection: Long
|
override var lastConnection: Long
|
||||||
get() = podState.lastConnection
|
get() = podState.lastConnection
|
||||||
|
@ -50,54 +56,77 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
||||||
store()
|
store()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val lastUpdated: Long = podState.lastUpdated
|
override val lastUpdated: Long
|
||||||
|
get() = podState.lastUpdated
|
||||||
|
|
||||||
override val messageSequenceNumber: Short = podState.messageSequenceNumber
|
override val messageSequenceNumber: Short
|
||||||
|
get() = podState.messageSequenceNumber
|
||||||
|
|
||||||
override val sequenceNumberOfLastProgrammingCommand: Short? = podState.sequenceNumberOfLastProgrammingCommand
|
override val sequenceNumberOfLastProgrammingCommand: Short?
|
||||||
|
get() = podState.sequenceNumberOfLastProgrammingCommand
|
||||||
|
|
||||||
override val activationTime: Long? = podState.activationTime
|
override val activationTime: Long?
|
||||||
|
get() = podState.activationTime
|
||||||
|
|
||||||
override val uniqueId: Long? = podState.uniqueId
|
override val uniqueId: Long?
|
||||||
|
get() = podState.uniqueId
|
||||||
|
|
||||||
override val bluetoothAddress: String? = podState.bluetoothAddress
|
override val bluetoothAddress: String?
|
||||||
|
get() = podState.bluetoothAddress
|
||||||
|
|
||||||
override val bluetoothVersion: SoftwareVersion? = podState.bleVersion
|
override val bluetoothVersion: SoftwareVersion?
|
||||||
|
get() = podState.bleVersion
|
||||||
|
|
||||||
override val firmwareVersion: SoftwareVersion? = podState.firmwareVersion
|
override val firmwareVersion: SoftwareVersion?
|
||||||
|
get() = podState.firmwareVersion
|
||||||
|
|
||||||
override val lotNumber: Long? = podState.lotNumber
|
override val lotNumber: Long?
|
||||||
|
get() = podState.lotNumber
|
||||||
|
|
||||||
override val podSequenceNumber: Long? = podState.podSequenceNumber
|
override val podSequenceNumber: Long?
|
||||||
|
get() = podState.podSequenceNumber
|
||||||
|
|
||||||
override val pulseRate: Short? = podState.pulseRate
|
override val pulseRate: Short?
|
||||||
|
get() = podState.pulseRate
|
||||||
|
|
||||||
override val primePulseRate: Short? = podState.primePulseRate
|
override val primePulseRate: Short?
|
||||||
|
get() = podState.primePulseRate
|
||||||
|
|
||||||
override val podLifeInHours: Short? = podState.podLifeInHours
|
override val podLifeInHours: Short?
|
||||||
|
get() = podState.podLifeInHours
|
||||||
|
|
||||||
override val firstPrimeBolusVolume: Short? = podState.firstPrimeBolusVolume
|
override val firstPrimeBolusVolume: Short?
|
||||||
|
get() = podState.firstPrimeBolusVolume
|
||||||
|
|
||||||
override val secondPrimeBolusVolume: Short? = podState.secondPrimeBolusVolume
|
override val secondPrimeBolusVolume: Short?
|
||||||
|
get() = podState.secondPrimeBolusVolume
|
||||||
|
|
||||||
override val pulsesDelivered: Short? = podState.pulsesDelivered
|
override val pulsesDelivered: Short?
|
||||||
|
get() = podState.pulsesDelivered
|
||||||
|
|
||||||
override val pulsesRemaining: Short? = podState.pulsesRemaining
|
override val pulsesRemaining: Short?
|
||||||
|
get() = podState.pulsesRemaining
|
||||||
|
|
||||||
override val podStatus: PodStatus? = podState.podStatus
|
override val podStatus: PodStatus?
|
||||||
|
get() = podState.podStatus
|
||||||
|
|
||||||
override val deliveryStatus: DeliveryStatus? = podState.deliveryStatus
|
override val deliveryStatus: DeliveryStatus?
|
||||||
|
get() = podState.deliveryStatus
|
||||||
|
|
||||||
override val minutesSinceActivation: Short? = podState.minutesSinceActivation
|
override val minutesSinceActivation: Short?
|
||||||
|
get() = podState.minutesSinceActivation
|
||||||
|
|
||||||
override val activeAlerts: EnumSet<AlertSlot>? = podState.activeAlerts
|
override val activeAlerts: EnumSet<AlertSlot>?
|
||||||
|
get() = podState.activeAlerts
|
||||||
|
|
||||||
override val tempBasal: OmnipodDashPodStateManager.TempBasal? = podState.tempBasal
|
override val tempBasal: OmnipodDashPodStateManager.TempBasal?
|
||||||
|
get() = podState.tempBasal
|
||||||
|
|
||||||
override val tempBasalActive: Boolean
|
override val tempBasalActive: Boolean
|
||||||
get() = tempBasal != null && tempBasal.startTime + tempBasal.durationInMinutes * 60 * 1000 > System.currentTimeMillis()
|
get() = tempBasal != null && tempBasal!!.startTime + tempBasal!!.durationInMinutes * 60 * 1000 > System.currentTimeMillis()
|
||||||
|
|
||||||
override val basalProgram: BasalProgram? = podState.basalProgram
|
override val basalProgram: BasalProgram?
|
||||||
|
get() = podState.basalProgram
|
||||||
|
|
||||||
override fun increaseMessageSequenceNumber() {
|
override fun increaseMessageSequenceNumber() {
|
||||||
podState.messageSequenceNumber = ((podState.messageSequenceNumber.toInt() + 1) and 0x0f).toShort()
|
podState.messageSequenceNumber = ((podState.messageSequenceNumber.toInt() + 1) and 0x0f).toShort()
|
||||||
|
@ -105,42 +134,42 @@ 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) {
|
||||||
podState.bleVersion = SoftwareVersion(response.getBleVersionMajor(), response.getBleVersionMinor(), response.getBleVersionInterim())
|
podState.bleVersion = SoftwareVersion(response.bleVersionMajor, response.bleVersionMinor, response.bleVersionInterim)
|
||||||
podState.firmwareVersion = SoftwareVersion(response.getFirmwareVersionMajor(), response.getFirmwareVersionMinor(), response.getFirmwareVersionInterim())
|
podState.firmwareVersion = SoftwareVersion(response.firmwareVersionMajor, response.firmwareVersionMinor, response.firmwareVersionInterim)
|
||||||
podState.podStatus = response.getPodStatus()
|
podState.podStatus = response.podStatus
|
||||||
podState.lotNumber = response.getLotNumber()
|
podState.lotNumber = response.lotNumber
|
||||||
podState.podSequenceNumber = response.getPodSequenceNumber()
|
podState.podSequenceNumber = response.podSequenceNumber
|
||||||
|
|
||||||
podState.lastUpdated = System.currentTimeMillis()
|
podState.lastUpdated = System.currentTimeMillis()
|
||||||
store()
|
store()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateFromSetUniqueIdResponse(response: SetUniqueIdResponse) {
|
override fun updateFromSetUniqueIdResponse(response: SetUniqueIdResponse) {
|
||||||
podState.pulseRate = response.getDeliveryRate()
|
podState.pulseRate = response.pumpRate
|
||||||
podState.primePulseRate = response.getPrimeRate()
|
podState.primePulseRate = response.primePumpRate
|
||||||
podState.firstPrimeBolusVolume = response.getNumberOfPrimePulses()
|
podState.firstPrimeBolusVolume = response.numberOfPrimePulses
|
||||||
podState.secondPrimeBolusVolume = response.getNumberOfEngagingClutchDrivePulses()
|
podState.secondPrimeBolusVolume = response.numberOfEngagingClutchDrivePulses
|
||||||
podState.podLifeInHours = response.getPodExpirationTimeInHours()
|
podState.podLifeInHours = response.podExpirationTimeInHours
|
||||||
podState.bleVersion = SoftwareVersion(response.getBleVersionMajor(), response.getBleVersionMinor(), response.getBleVersionInterim())
|
podState.bleVersion = SoftwareVersion(response.bleVersionMajor, response.bleVersionMinor, response.bleVersionInterim)
|
||||||
podState.firmwareVersion = SoftwareVersion(response.getFirmwareVersionMajor(), response.getFirmwareVersionMinor(), response.getFirmwareVersionInterim())
|
podState.firmwareVersion = SoftwareVersion(response.firmwareVersionMajor, response.firmwareVersionMinor, response.firmwareVersionInterim)
|
||||||
podState.podStatus = response.getPodStatus()
|
podState.podStatus = response.podStatus
|
||||||
podState.lotNumber = response.getLotNumber()
|
podState.lotNumber = response.lotNumber
|
||||||
podState.podSequenceNumber = response.getPodSequenceNumber()
|
podState.podSequenceNumber = response.podSequenceNumber
|
||||||
podState.uniqueId = response.getUniqueIdReceivedInCommand()
|
podState.uniqueId = response.uniqueIdReceivedInCommand
|
||||||
|
|
||||||
podState.lastUpdated = System.currentTimeMillis()
|
podState.lastUpdated = System.currentTimeMillis()
|
||||||
store()
|
store()
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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()])
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.activation.viewmodel.action
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.activation.viewmodel.action
|
||||||
|
|
||||||
import android.os.AsyncTask
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult
|
import info.nightscout.androidaps.data.PumpEnactResult
|
||||||
|
@ -8,13 +7,12 @@ import info.nightscout.androidaps.logging.AAPSLogger
|
||||||
import info.nightscout.androidaps.logging.LTag
|
import info.nightscout.androidaps.logging.LTag
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InitializePodViewModel
|
import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InitializePodViewModel
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.R
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.R
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManager
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class DashInitializePodViewModel @Inject constructor(private val aapsLogger: AAPSLogger,
|
class DashInitializePodViewModel @Inject constructor(private val aapsLogger: AAPSLogger,
|
||||||
private val injector: HasAndroidInjector,
|
private val injector: HasAndroidInjector,
|
||||||
private val bleManager: OmnipodDashBleManager) : InitializePodViewModel() {
|
private val omnipodManager: OmnipodDashManager) : InitializePodViewModel() {
|
||||||
|
|
||||||
override fun isPodInAlarm(): Boolean = false // TODO
|
override fun isPodInAlarm(): Boolean = false // TODO
|
||||||
|
|
||||||
|
@ -24,14 +22,11 @@ class DashInitializePodViewModel @Inject constructor(private val aapsLogger: AAP
|
||||||
|
|
||||||
override fun doExecuteAction(): PumpEnactResult {
|
override fun doExecuteAction(): PumpEnactResult {
|
||||||
// TODO FIRST STEP OF ACTIVATION
|
// TODO FIRST STEP OF ACTIVATION
|
||||||
AsyncTask.execute {
|
val disposable = omnipodManager.activatePodPart1().subscribe(
|
||||||
try {
|
{ podEvent -> aapsLogger.debug(LTag.PUMP, "Received PodEvent in Pod activation part 1: $podEvent") },
|
||||||
bleManager.connect()
|
{ throwable -> aapsLogger.error(LTag.PUMP, "Error in Pod activation part 1: $throwable") },
|
||||||
} catch (e: Exception) {
|
{ aapsLogger.debug("Pod activation part 1 completed") }
|
||||||
aapsLogger.error(LTag.PUMP, "TEST ACTIVATE Exception" + e.toString() + ExceptionUtils.getStackTrace(e))
|
)
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PumpEnactResult(injector).success(false).comment("not implemented")
|
return PumpEnactResult(injector).success(false).comment("not implemented")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.util
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.data.Profile
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BasalProgram
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
fun mapProfileToBasalProgram(profile: Profile): BasalProgram {
|
||||||
|
val basalValues = profile.basalValues
|
||||||
|
?: throw IllegalArgumentException("Basal values can not be null")
|
||||||
|
if (basalValues.isEmpty()) {
|
||||||
|
throw IllegalArgumentException("Basal values should contain values")
|
||||||
|
}
|
||||||
|
|
||||||
|
val entries: MutableList<BasalProgram.Segment> = ArrayList()
|
||||||
|
|
||||||
|
var previousBasalValue: Profile.ProfileValue? = null
|
||||||
|
|
||||||
|
for (basalValue in basalValues) {
|
||||||
|
if (basalValue.timeAsSeconds >= 86_400) {
|
||||||
|
throw IllegalArgumentException("Basal segment start time can not be greater than 86400")
|
||||||
|
}
|
||||||
|
if (basalValue.timeAsSeconds < 0) {
|
||||||
|
throw IllegalArgumentException("Basal segment start time can not be less than 0")
|
||||||
|
}
|
||||||
|
if (basalValue.timeAsSeconds % 1_800 != 0) {
|
||||||
|
throw IllegalArgumentException("Basal segment time should be dividable by 30 minutes")
|
||||||
|
}
|
||||||
|
|
||||||
|
val startSlotIndex = (basalValue.timeAsSeconds / 1800).toShort()
|
||||||
|
|
||||||
|
if (previousBasalValue != null) {
|
||||||
|
entries.add(
|
||||||
|
BasalProgram.Segment(
|
||||||
|
(previousBasalValue!!.timeAsSeconds / 1800).toShort(),
|
||||||
|
startSlotIndex,
|
||||||
|
(PumpType.Omnipod_Dash.determineCorrectBasalSize(previousBasalValue.value) * 100).roundToInt()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries.size == 0 && basalValue.timeAsSeconds != 0) {
|
||||||
|
throw java.lang.IllegalArgumentException("First basal segment start time should be 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries.size > 0 && entries[entries.size - 1].endSlotIndex != startSlotIndex) {
|
||||||
|
throw IllegalArgumentException("Illegal start time for basal segment: does not match previous previous segment's end time")
|
||||||
|
}
|
||||||
|
|
||||||
|
previousBasalValue = basalValue
|
||||||
|
}
|
||||||
|
|
||||||
|
entries.add(
|
||||||
|
BasalProgram.Segment(
|
||||||
|
(previousBasalValue!!.timeAsSeconds / 1800).toShort(),
|
||||||
|
48,
|
||||||
|
(PumpType.Omnipod_Dash.determineCorrectBasalSize(previousBasalValue.value) * 100).roundToInt()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return BasalProgram(entries)
|
||||||
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response
|
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
|
|
||||||
import org.apache.commons.codec.DecoderException
|
import org.apache.commons.codec.DecoderException
|
||||||
import org.apache.commons.codec.binary.Hex
|
import org.apache.commons.codec.binary.Hex
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
|
@ -17,24 +16,24 @@ class SetUniqueIdResponseTest {
|
||||||
Assert.assertNotSame(encoded, response.encoded)
|
Assert.assertNotSame(encoded, response.encoded)
|
||||||
Assert.assertEquals(ResponseType.ACTIVATION_RESPONSE, response.responseType)
|
Assert.assertEquals(ResponseType.ACTIVATION_RESPONSE, response.responseType)
|
||||||
Assert.assertEquals(ResponseType.ActivationResponseType.SET_UNIQUE_ID_RESPONSE, response.activationResponseType)
|
Assert.assertEquals(ResponseType.ActivationResponseType.SET_UNIQUE_ID_RESPONSE, response.activationResponseType)
|
||||||
Assert.assertEquals(ResponseType.ACTIVATION_RESPONSE.value, response.getMessageType())
|
Assert.assertEquals(ResponseType.ACTIVATION_RESPONSE.value, response.messageType)
|
||||||
Assert.assertEquals(27.toShort(), response.getMessageLength())
|
Assert.assertEquals(27.toShort(), response.messageLength)
|
||||||
Assert.assertEquals(5000.toShort(), response.getPulseVolumeInTenThousandthMicroLiter())
|
Assert.assertEquals(5000.toShort(), response.pulseVolumeInTenThousandthMicroLiter)
|
||||||
Assert.assertEquals(16.toShort(), response.getDeliveryRate())
|
Assert.assertEquals(16.toShort(), response.pumpRate)
|
||||||
Assert.assertEquals(8.toShort(), response.getPrimeRate())
|
Assert.assertEquals(8.toShort(), response.primePumpRate)
|
||||||
Assert.assertEquals(52.toShort(), response.getNumberOfEngagingClutchDrivePulses())
|
Assert.assertEquals(52.toShort(), response.numberOfEngagingClutchDrivePulses)
|
||||||
Assert.assertEquals(10.toShort(), response.getNumberOfPrimePulses())
|
Assert.assertEquals(10.toShort(), response.numberOfPrimePulses)
|
||||||
Assert.assertEquals(80.toShort(), response.getPodExpirationTimeInHours())
|
Assert.assertEquals(80.toShort(), response.podExpirationTimeInHours)
|
||||||
Assert.assertEquals(4.toShort(), response.getFirmwareVersionMajor())
|
Assert.assertEquals(4.toShort(), response.firmwareVersionMajor)
|
||||||
Assert.assertEquals(10.toShort(), response.getFirmwareVersionMinor())
|
Assert.assertEquals(10.toShort(), response.firmwareVersionMinor)
|
||||||
Assert.assertEquals(0.toShort(), response.getFirmwareVersionInterim())
|
Assert.assertEquals(0.toShort(), response.firmwareVersionInterim)
|
||||||
Assert.assertEquals(1.toShort(), response.getBleVersionMajor())
|
Assert.assertEquals(1.toShort(), response.bleVersionMajor)
|
||||||
Assert.assertEquals(3.toShort(), response.getBleVersionMinor())
|
Assert.assertEquals(3.toShort(), response.bleVersionMinor)
|
||||||
Assert.assertEquals(0.toShort(), response.getBleVersionInterim())
|
Assert.assertEquals(0.toShort(), response.bleVersionInterim)
|
||||||
Assert.assertEquals(4.toShort(), response.getProductId())
|
Assert.assertEquals(4.toShort(), response.productId)
|
||||||
Assert.assertEquals(PodStatus.UID_SET, response.getPodStatus())
|
Assert.assertEquals(PodStatus.UID_SET, response.podStatus)
|
||||||
Assert.assertEquals(135556289L, response.getLotNumber())
|
Assert.assertEquals(135556289L, response.lotNumber)
|
||||||
Assert.assertEquals(611540L, response.getPodSequenceNumber())
|
Assert.assertEquals(611540L, response.podSequenceNumber)
|
||||||
Assert.assertEquals(37879809L, response.getUniqueIdReceivedInCommand())
|
Assert.assertEquals(37879809L, response.uniqueIdReceivedInCommand)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response
|
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
|
|
||||||
import org.apache.commons.codec.DecoderException
|
import org.apache.commons.codec.DecoderException
|
||||||
import org.apache.commons.codec.binary.Hex
|
import org.apache.commons.codec.binary.Hex
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
|
@ -17,20 +16,20 @@ class VersionResponseTest {
|
||||||
Assert.assertNotSame(encoded, response.encoded)
|
Assert.assertNotSame(encoded, response.encoded)
|
||||||
Assert.assertEquals(ResponseType.ACTIVATION_RESPONSE, response.responseType)
|
Assert.assertEquals(ResponseType.ACTIVATION_RESPONSE, response.responseType)
|
||||||
Assert.assertEquals(ResponseType.ActivationResponseType.GET_VERSION_RESPONSE, response.activationResponseType)
|
Assert.assertEquals(ResponseType.ActivationResponseType.GET_VERSION_RESPONSE, response.activationResponseType)
|
||||||
Assert.assertEquals(ResponseType.ACTIVATION_RESPONSE.value, response.getMessageType())
|
Assert.assertEquals(ResponseType.ACTIVATION_RESPONSE.value, response.messageType)
|
||||||
Assert.assertEquals(21.toShort(), response.getMessageLength())
|
Assert.assertEquals(21.toShort(), response.messageLength)
|
||||||
Assert.assertEquals(4.toShort(), response.getFirmwareVersionMajor())
|
Assert.assertEquals(4.toShort(), response.firmwareVersionMajor)
|
||||||
Assert.assertEquals(10.toShort(), response.getFirmwareVersionMinor())
|
Assert.assertEquals(10.toShort(), response.firmwareVersionMinor)
|
||||||
Assert.assertEquals(0.toShort(), response.getFirmwareVersionInterim())
|
Assert.assertEquals(0.toShort(), response.firmwareVersionInterim)
|
||||||
Assert.assertEquals(1.toShort(), response.getBleVersionMajor())
|
Assert.assertEquals(1.toShort(), response.bleVersionMajor)
|
||||||
Assert.assertEquals(3.toShort(), response.getBleVersionMinor())
|
Assert.assertEquals(3.toShort(), response.bleVersionMinor)
|
||||||
Assert.assertEquals(0.toShort(), response.getBleVersionInterim())
|
Assert.assertEquals(0.toShort(), response.bleVersionInterim)
|
||||||
Assert.assertEquals(4.toShort(), response.getProductId())
|
Assert.assertEquals(4.toShort(), response.productId)
|
||||||
Assert.assertEquals(PodStatus.FILLED, response.getPodStatus())
|
Assert.assertEquals(PodStatus.FILLED, response.podStatus)
|
||||||
Assert.assertEquals(135556289L, response.getLotNumber())
|
Assert.assertEquals(135556289L, response.lotNumber)
|
||||||
Assert.assertEquals(611540L, response.getPodSequenceNumber())
|
Assert.assertEquals(611540L, response.podSequenceNumber)
|
||||||
Assert.assertEquals(0.toByte(), response.getRssi())
|
Assert.assertEquals(0.toByte(), response.rssi)
|
||||||
Assert.assertEquals(0.toByte(), response.getReceiverLowerGain())
|
Assert.assertEquals(0.toByte(), response.receiverLowerGain)
|
||||||
Assert.assertEquals(4294967295L, response.getUniqueIdReceivedInCommand())
|
Assert.assertEquals(4294967295L, response.uniqueIdReceivedInCommand)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.util
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.data.Profile
|
||||||
|
import info.nightscout.androidaps.data.Profile.ProfileValue
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BasalProgram
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.rules.ExpectedException
|
||||||
|
import org.mockito.Mockito
|
||||||
|
import org.powermock.api.mockito.PowerMockito
|
||||||
|
|
||||||
|
class FunctionsTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
@JvmField var thrown = ExpectedException.none()
|
||||||
|
|
||||||
|
@Test fun validProfile() {
|
||||||
|
val profile = Mockito.mock(Profile::class.java)
|
||||||
|
val value1 = Mockito.mock(ProfileValue::class.java)
|
||||||
|
value1.timeAsSeconds = 0
|
||||||
|
value1.value = 0.5
|
||||||
|
val value2 = Mockito.mock(ProfileValue::class.java)
|
||||||
|
value2.timeAsSeconds = 18000
|
||||||
|
value2.value = 1.0
|
||||||
|
val value3 = Mockito.mock(ProfileValue::class.java)
|
||||||
|
value3.timeAsSeconds = 50400
|
||||||
|
value3.value = 3.05
|
||||||
|
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOf(
|
||||||
|
value1,
|
||||||
|
value2,
|
||||||
|
value3
|
||||||
|
))
|
||||||
|
val basalProgram: BasalProgram = mapProfileToBasalProgram(profile)
|
||||||
|
val entries: List<BasalProgram.Segment> = basalProgram.segments
|
||||||
|
assertEquals(3, entries.size)
|
||||||
|
val entry1: BasalProgram.Segment = entries[0]
|
||||||
|
assertEquals(0.toShort(), entry1.startSlotIndex)
|
||||||
|
assertEquals(50, entry1.basalRateInHundredthUnitsPerHour)
|
||||||
|
assertEquals(10.toShort(), entry1.endSlotIndex)
|
||||||
|
val entry2: BasalProgram.Segment = entries[1]
|
||||||
|
assertEquals(10.toShort(), entry2.startSlotIndex)
|
||||||
|
assertEquals(100, entry2.basalRateInHundredthUnitsPerHour)
|
||||||
|
assertEquals(28.toShort(), entry2.endSlotIndex)
|
||||||
|
val entry3: BasalProgram.Segment = entries[2]
|
||||||
|
assertEquals(28.toShort(), entry3.startSlotIndex)
|
||||||
|
assertEquals(305, entry3.basalRateInHundredthUnitsPerHour)
|
||||||
|
assertEquals(48.toShort(), entry3.endSlotIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun invalidProfileNullEntries() {
|
||||||
|
thrown.expect(IllegalArgumentException::class.java)
|
||||||
|
thrown.expectMessage("Basal values can not be null")
|
||||||
|
mapProfileToBasalProgram(Mockito.mock(Profile::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun invalidProfileZeroEntries() {
|
||||||
|
thrown.expect(IllegalArgumentException::class.java)
|
||||||
|
thrown.expectMessage("Basal values should contain values")
|
||||||
|
val profile = Mockito.mock(Profile::class.java)
|
||||||
|
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOfNulls(0))
|
||||||
|
mapProfileToBasalProgram(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun invalidProfileNonZeroOffset() {
|
||||||
|
thrown.expect(IllegalArgumentException::class.java)
|
||||||
|
thrown.expectMessage("First basal segment start time should be 0")
|
||||||
|
val profile = Mockito.mock(Profile::class.java)
|
||||||
|
val value = Mockito.mock(ProfileValue::class.java)
|
||||||
|
value.timeAsSeconds = 1800
|
||||||
|
value.value = 0.5
|
||||||
|
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOf(
|
||||||
|
value))
|
||||||
|
mapProfileToBasalProgram(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun invalidProfileMoreThan24Hours() {
|
||||||
|
thrown.expect(IllegalArgumentException::class.java)
|
||||||
|
thrown.expectMessage("Basal segment start time can not be greater than 86400")
|
||||||
|
|
||||||
|
val profile = Mockito.mock(Profile::class.java)
|
||||||
|
val value1 = Mockito.mock(ProfileValue::class.java)
|
||||||
|
value1.timeAsSeconds = 0
|
||||||
|
value1.value = 0.5
|
||||||
|
val value2 = Mockito.mock(ProfileValue::class.java)
|
||||||
|
value2.timeAsSeconds = 86400
|
||||||
|
value2.value = 0.5
|
||||||
|
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOf(
|
||||||
|
value1,
|
||||||
|
value2
|
||||||
|
))
|
||||||
|
mapProfileToBasalProgram(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun invalidProfileNegativeOffset() {
|
||||||
|
thrown.expect(IllegalArgumentException::class.java)
|
||||||
|
thrown.expectMessage("Basal segment start time can not be less than 0")
|
||||||
|
val profile = Mockito.mock(Profile::class.java)
|
||||||
|
val value = Mockito.mock(ProfileValue::class.java)
|
||||||
|
value.timeAsSeconds = -1
|
||||||
|
value.value = 0.5
|
||||||
|
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOf(
|
||||||
|
value))
|
||||||
|
mapProfileToBasalProgram(profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test fun roundsToSupportedPrecision() {
|
||||||
|
val profile = Mockito.mock(Profile::class.java)
|
||||||
|
val value = Mockito.mock(ProfileValue::class.java)
|
||||||
|
value.timeAsSeconds = 0
|
||||||
|
value.value = 0.04
|
||||||
|
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOf(
|
||||||
|
value))
|
||||||
|
val basalProgram: BasalProgram = mapProfileToBasalProgram(profile)
|
||||||
|
val basalProgramElement: BasalProgram.Segment = basalProgram.segments[0]
|
||||||
|
assertEquals(5, basalProgramElement.basalRateInHundredthUnitsPerHour)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue