ktlint format
This commit is contained in:
parent
3ebcc1c71e
commit
77c816e813
146 changed files with 557 additions and 467 deletions
|
@ -30,7 +30,9 @@ class DashHistoryTest {
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||||
database = Room.inMemoryDatabaseBuilder(
|
database = Room.inMemoryDatabaseBuilder(
|
||||||
context, DashHistoryDatabase::class.java).build()
|
context,
|
||||||
|
DashHistoryDatabase::class.java
|
||||||
|
).build()
|
||||||
dao = database.historyRecordDao()
|
dao = database.historyRecordDao()
|
||||||
dashHistory = DashHistory(dao, HistoryMapper())
|
dashHistory = DashHistory(dao, HistoryMapper())
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ class RxSchedulerRule(val scheduler: Scheduler) : TestRule {
|
||||||
RxJavaPlugins.reset()
|
RxJavaPlugins.reset()
|
||||||
RxAndroidPlugins.reset()
|
RxAndroidPlugins.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -29,5 +29,4 @@ class OmnipodDashHistoryModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
internal fun provideDashHistory(dao: HistoryRecordDao, historyMapper: HistoryMapper) =
|
internal fun provideDashHistory(dao: HistoryRecordDao, historyMapper: HistoryMapper) =
|
||||||
DashHistory(dao, historyMapper)
|
DashHistory(dao, historyMapper)
|
||||||
|
|
||||||
}
|
}
|
|
@ -50,7 +50,8 @@ class OmnipodDashManagerImpl @Inject constructor(
|
||||||
|
|
||||||
private fun observeSendProgramBolusCommand(units: Double, rateInEighthPulsesPerSeconds: Byte, confirmationBeeps: Boolean, completionBeeps: Boolean): Observable<PodEvent> {
|
private fun observeSendProgramBolusCommand(units: Double, rateInEighthPulsesPerSeconds: Byte, confirmationBeeps: Boolean, completionBeeps: Boolean): Observable<PodEvent> {
|
||||||
return Observable.defer {
|
return Observable.defer {
|
||||||
bleManager.sendCommand(ProgramBolusCommand.Builder()
|
bleManager.sendCommand(
|
||||||
|
ProgramBolusCommand.Builder()
|
||||||
.setUniqueId(podStateManager.uniqueId!!.toInt())
|
.setUniqueId(podStateManager.uniqueId!!.toInt())
|
||||||
.setSequenceNumber(podStateManager.messageSequenceNumber)
|
.setSequenceNumber(podStateManager.messageSequenceNumber)
|
||||||
.setNonce(1229869870) // TODO
|
.setNonce(1229869870) // TODO
|
||||||
|
@ -78,13 +79,15 @@ class OmnipodDashManagerImpl @Inject constructor(
|
||||||
get() = Observable.defer {
|
get() = Observable.defer {
|
||||||
observeSendGetPodStatusCommand()
|
observeSendGetPodStatusCommand()
|
||||||
.ignoreElements() //
|
.ignoreElements() //
|
||||||
.andThen(Observable.defer {
|
.andThen(
|
||||||
|
Observable.defer {
|
||||||
if (podStateManager.podStatus == PodStatus.RUNNING_ABOVE_MIN_VOLUME) {
|
if (podStateManager.podStatus == PodStatus.RUNNING_ABOVE_MIN_VOLUME) {
|
||||||
Observable.empty()
|
Observable.empty()
|
||||||
} else {
|
} else {
|
||||||
Observable.error(IllegalStateException("Unexpected Pod status"))
|
Observable.error(IllegalStateException("Unexpected Pod status"))
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun observeSendProgramAlertsCommand(alertConfigurations: List<AlertConfiguration>, multiCommandFlag: Boolean = false): Observable<PodEvent> {
|
private fun observeSendProgramAlertsCommand(alertConfigurations: List<AlertConfiguration>, multiCommandFlag: Boolean = false): Observable<PodEvent> {
|
||||||
|
@ -119,32 +122,38 @@ class OmnipodDashManagerImpl @Inject constructor(
|
||||||
get() = Observable.defer {
|
get() = Observable.defer {
|
||||||
observeSendGetPodStatusCommand()
|
observeSendGetPodStatusCommand()
|
||||||
.ignoreElements() //
|
.ignoreElements() //
|
||||||
.andThen(Observable.defer {
|
.andThen(
|
||||||
|
Observable.defer {
|
||||||
if (podStateManager.podStatus == PodStatus.CLUTCH_DRIVE_ENGAGED) {
|
if (podStateManager.podStatus == PodStatus.CLUTCH_DRIVE_ENGAGED) {
|
||||||
Observable.empty()
|
Observable.empty()
|
||||||
} else {
|
} else {
|
||||||
Observable.error(IllegalStateException("Unexpected Pod status"))
|
Observable.error(IllegalStateException("Unexpected Pod status"))
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val observeSendSetUniqueIdCommand: Observable<PodEvent>
|
private val observeSendSetUniqueIdCommand: Observable<PodEvent>
|
||||||
get() = Observable.defer {
|
get() = Observable.defer {
|
||||||
bleManager.sendCommand(SetUniqueIdCommand.Builder() //
|
bleManager.sendCommand(
|
||||||
|
SetUniqueIdCommand.Builder() //
|
||||||
.setSequenceNumber(podStateManager.messageSequenceNumber) //
|
.setSequenceNumber(podStateManager.messageSequenceNumber) //
|
||||||
.setUniqueId(podStateManager.uniqueId!!.toInt()) //
|
.setUniqueId(podStateManager.uniqueId!!.toInt()) //
|
||||||
.setLotNumber(podStateManager.lotNumber!!.toInt()) //
|
.setLotNumber(podStateManager.lotNumber!!.toInt()) //
|
||||||
.setPodSequenceNumber(podStateManager.podSequenceNumber!!.toInt())
|
.setPodSequenceNumber(podStateManager.podSequenceNumber!!.toInt())
|
||||||
.setInitializationTime(Date())
|
.setInitializationTime(Date())
|
||||||
.build()) //
|
.build()
|
||||||
|
) //
|
||||||
}
|
}
|
||||||
|
|
||||||
private val observeSendGetVersionCommand: Observable<PodEvent>
|
private val observeSendGetVersionCommand: Observable<PodEvent>
|
||||||
get() = Observable.defer {
|
get() = Observable.defer {
|
||||||
bleManager.sendCommand(GetVersionCommand.Builder() //
|
bleManager.sendCommand(
|
||||||
|
GetVersionCommand.Builder() //
|
||||||
.setSequenceNumber(podStateManager.messageSequenceNumber) //
|
.setSequenceNumber(podStateManager.messageSequenceNumber) //
|
||||||
.setUniqueId(DEFAULT_UNIQUE_ID) //
|
.setUniqueId(DEFAULT_UNIQUE_ID) //
|
||||||
.build()) //
|
.build()
|
||||||
|
) //
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun activatePodPart1(lowReservoirAlertTrigger: AlertTrigger.ReservoirVolumeTrigger?): Observable<PodEvent> {
|
override fun activatePodPart1(lowReservoirAlertTrigger: AlertTrigger.ReservoirVolumeTrigger?): Observable<PodEvent> {
|
||||||
|
@ -277,7 +286,8 @@ class OmnipodDashManagerImpl @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (podStateManager.activationProgress.isBefore(ActivationProgress.UPDATED_EXPIRATION_ALERTS)) {
|
if (podStateManager.activationProgress.isBefore(ActivationProgress.UPDATED_EXPIRATION_ALERTS)) {
|
||||||
observables.add(observeSendProgramAlertsCommand(
|
observables.add(
|
||||||
|
observeSendProgramAlertsCommand(
|
||||||
listOf(
|
listOf(
|
||||||
// FIXME use user configured expiration alert
|
// FIXME use user configured expiration alert
|
||||||
AlertConfiguration(
|
AlertConfiguration(
|
||||||
|
@ -300,7 +310,8 @@ class OmnipodDashManagerImpl @Inject constructor(
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
multiCommandFlag = true
|
multiCommandFlag = true
|
||||||
).doOnComplete(ActivationProgressUpdater(ActivationProgress.UPDATED_EXPIRATION_ALERTS)))
|
).doOnComplete(ActivationProgressUpdater(ActivationProgress.UPDATED_EXPIRATION_ALERTS))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (podStateManager.activationProgress.isBefore(ActivationProgress.PROGRAMMED_BASAL)) {
|
if (podStateManager.activationProgress.isBefore(ActivationProgress.PROGRAMMED_BASAL)) {
|
||||||
observables.add(
|
observables.add(
|
||||||
|
@ -424,7 +435,6 @@ class OmnipodDashManagerImpl @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class ErrorInterceptor : Consumer<Throwable> {
|
inner class ErrorInterceptor : Consumer<Throwable> {
|
||||||
|
@ -432,7 +442,6 @@ class OmnipodDashManagerImpl @Inject constructor(
|
||||||
override fun accept(throwable: Throwable) {
|
override fun accept(throwable: Throwable) {
|
||||||
logger.debug(LTag.PUMP, "Intercepted error in OmnipodDashManagerImpl: ${throwable.javaClass.simpleName}")
|
logger.debug(LTag.PUMP, "Intercepted error in OmnipodDashManagerImpl: ${throwable.javaClass.simpleName}")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class ActivationProgressUpdater(private val value: ActivationProgress) : Action {
|
inner class ActivationProgressUpdater(private val value: ActivationProgress) : Action {
|
||||||
|
@ -440,6 +449,5 @@ class OmnipodDashManagerImpl @Inject constructor(
|
||||||
override fun run() {
|
override fun run() {
|
||||||
podStateManager.activationProgress = value
|
podStateManager.activationProgress = value
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ data class Id(val address: ByteArray) {
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
val asInt = ByteBuffer.wrap(address).int
|
val asInt = ByteBuffer.wrap(address).int
|
||||||
return "${asInt}/${address.toHex()}"
|
return "$asInt/${address.toHex()}"
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -33,5 +33,4 @@ data class Id(val address: ByteArray) {
|
||||||
return Id(ByteBuffer.allocate(4).putInt(v).array())
|
return Id(ByteBuffer.allocate(4).putInt(v).array())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,10 @@ class OmnipodDashBleManagerImpl @Inject constructor(private val context: Context
|
||||||
// TODO: locking?
|
// TODO: locking?
|
||||||
val podDevice = bluetoothAdapter.getRemoteDevice(podAddress)
|
val podDevice = bluetoothAdapter.getRemoteDevice(podAddress)
|
||||||
val incomingPackets: Map<CharacteristicType, BlockingQueue<ByteArray>> =
|
val incomingPackets: Map<CharacteristicType, BlockingQueue<ByteArray>> =
|
||||||
mapOf(CharacteristicType.CMD to LinkedBlockingDeque(),
|
mapOf(
|
||||||
CharacteristicType.DATA to LinkedBlockingDeque())
|
CharacteristicType.CMD to LinkedBlockingDeque(),
|
||||||
|
CharacteristicType.DATA to LinkedBlockingDeque()
|
||||||
|
)
|
||||||
val bleCommCallbacks = BleCommCallbacks(aapsLogger, incomingPackets)
|
val bleCommCallbacks = BleCommCallbacks(aapsLogger, incomingPackets)
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to $podAddress")
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to $podAddress")
|
||||||
var autoConnect = true
|
var autoConnect = true
|
||||||
|
@ -118,5 +120,4 @@ class OmnipodDashBleManagerImpl @Inject constructor(private val context: Context
|
||||||
private const val CONNECT_TIMEOUT_MS = 7000
|
private const val CONNECT_TIMEOUT_MS = 7000
|
||||||
const val CONTROLLER_ID = 4242 // TODO read from preferences or somewhere else.
|
const val CONTROLLER_ID = 4242 // TODO read from preferences or somewhere else.
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,7 +4,6 @@ import android.bluetooth.BluetoothGatt
|
||||||
import android.bluetooth.BluetoothGattCharacteristic
|
import android.bluetooth.BluetoothGattCharacteristic
|
||||||
import info.nightscout.androidaps.logging.AAPSLogger
|
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.dash.driver.comm.callbacks.BleCommCallbacks
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CharacteristicNotFoundException
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CharacteristicNotFoundException
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ServiceNotFoundException
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.ServiceNotFoundException
|
||||||
|
@ -29,8 +28,10 @@ class ServiceDiscoverer(private val logger: AAPSLogger, private val gatt: Blueto
|
||||||
?: throw CharacteristicNotFoundException(CharacteristicType.CMD.value)
|
?: throw CharacteristicNotFoundException(CharacteristicType.CMD.value)
|
||||||
val dataChar = service.getCharacteristic(CharacteristicType.DATA.uuid) // TODO: this is never used
|
val dataChar = service.getCharacteristic(CharacteristicType.DATA.uuid) // TODO: this is never used
|
||||||
?: throw CharacteristicNotFoundException(CharacteristicType.DATA.value)
|
?: throw CharacteristicNotFoundException(CharacteristicType.DATA.value)
|
||||||
var chars = mapOf(CharacteristicType.CMD to cmdChar,
|
var chars = mapOf(
|
||||||
CharacteristicType.DATA to dataChar)
|
CharacteristicType.CMD to cmdChar,
|
||||||
|
CharacteristicType.DATA to dataChar
|
||||||
|
)
|
||||||
return chars
|
return chars
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,8 +77,11 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP
|
||||||
} else {
|
} else {
|
||||||
CharacteristicWriteConfirmationError(status)
|
CharacteristicWriteConfirmationError(status)
|
||||||
}
|
}
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicWrite with status/char/value " +
|
aapsLogger.debug(
|
||||||
status + "/" + byValue(characteristic.uuid.toString()) + "/" + characteristic.value.toHex())
|
LTag.PUMPBTCOMM,
|
||||||
|
"OnCharacteristicWrite with status/char/value " +
|
||||||
|
status + "/" + byValue(characteristic.uuid.toString()) + "/" + characteristic.value.toHex()
|
||||||
|
)
|
||||||
try {
|
try {
|
||||||
if (writeQueue.size > 0) {
|
if (writeQueue.size > 0) {
|
||||||
aapsLogger.warn(LTag.PUMPBTCOMM, "Write confirm queue should be empty. found: " + writeQueue.size)
|
aapsLogger.warn(LTag.PUMPBTCOMM, "Write confirm queue should be empty. found: " + writeQueue.size)
|
||||||
|
@ -97,9 +100,12 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP
|
||||||
super.onCharacteristicChanged(gatt, characteristic)
|
super.onCharacteristicChanged(gatt, characteristic)
|
||||||
val payload = characteristic.value
|
val payload = characteristic.value
|
||||||
val characteristicType = byValue(characteristic.uuid.toString())
|
val characteristicType = byValue(characteristic.uuid.toString())
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "OnCharacteristicChanged with char/value " +
|
aapsLogger.debug(
|
||||||
|
LTag.PUMPBTCOMM,
|
||||||
|
"OnCharacteristicChanged with char/value " +
|
||||||
characteristicType + "/" +
|
characteristicType + "/" +
|
||||||
payload.toHex())
|
payload.toHex()
|
||||||
|
)
|
||||||
incomingPackets[characteristicType]!!.add(payload)
|
incomingPackets[characteristicType]!!.add(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +115,8 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP
|
||||||
?: throw TimeoutException()
|
?: throw TimeoutException()
|
||||||
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 {
|
||||||
|
|
|
@ -2,7 +2,8 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command
|
||||||
|
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
class BleCommandHello(controllerId: Int) : BleCommand(BleCommandType.HELLO,
|
class BleCommandHello(controllerId: Int) : BleCommand(
|
||||||
|
BleCommandType.HELLO,
|
||||||
ByteBuffer.allocate(6)
|
ByteBuffer.allocate(6)
|
||||||
.put(1.toByte()) // TODO find the meaning of this constant
|
.put(1.toByte()) // TODO find the meaning of this constant
|
||||||
.put(4.toByte()) // TODO find the meaning of this constant
|
.put(4.toByte()) // TODO find the meaning of this constant
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions
|
||||||
|
|
||||||
class CouldNotConfirmDescriptorWriteException(override val message: String?) : Exception(message) {
|
class CouldNotConfirmDescriptorWriteException(override val message: String?) : Exception(message) {
|
||||||
constructor(sent: String, confirmed: String) : this("Could not confirm write. Sent: {$sent} .Received: ${confirmed}")
|
constructor(sent: String, confirmed: String) : this("Could not confirm write. Sent: {$sent} .Received: $confirmed")
|
||||||
constructor(status: Int) : this("Could not confirm write. Write status: ${status}")
|
constructor(status: Int) : this("Could not confirm write. Write status: $status")
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions
|
||||||
|
|
||||||
class CouldNotConfirmWriteException(override val message: String?) : Exception(message) {
|
class CouldNotConfirmWriteException(override val message: String?) : Exception(message) {
|
||||||
constructor(sent: ByteArray, confirmed: ByteArray) : this("Could not confirm write. Sent: {$sent} .Received: ${confirmed}")
|
constructor(sent: ByteArray, confirmed: ByteArray) : this("Could not confirm write. Sent: {$sent} .Received: $confirmed")
|
||||||
constructor(status: Int) : this("Could not confirm write. Write status: ${status}")
|
constructor(status: Int) : this("Could not confirm write. Write status: $status")
|
||||||
}
|
}
|
|
@ -2,4 +2,4 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.excepti
|
||||||
|
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommand
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommand
|
||||||
|
|
||||||
class UnexpectedCommandException(val cmd: BleCommand) : Exception("Unexpected command: ${cmd}")
|
class UnexpectedCommandException(val cmd: BleCommand) : Exception("Unexpected command: $cmd")
|
||||||
|
|
|
@ -3,4 +3,4 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
|
||||||
import info.nightscout.androidaps.utils.extensions.toHex
|
import info.nightscout.androidaps.utils.extensions.toHex
|
||||||
|
|
||||||
class CrcMismatchException(val expected: Long, val actual: Long, val payload: ByteArray) :
|
class CrcMismatchException(val expected: Long, val actual: Long, val payload: ByteArray) :
|
||||||
Exception("CRC mismatch. Actual: ${actual}. Expected: ${expected}. Payload: ${payload.toHex()}")
|
Exception("CRC mismatch. Actual: $actual. Expected: $expected. Payload: ${payload.toHex()}")
|
||||||
|
|
|
@ -2,4 +2,4 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
|
||||||
|
|
||||||
import info.nightscout.androidaps.utils.extensions.toHex
|
import info.nightscout.androidaps.utils.extensions.toHex
|
||||||
|
|
||||||
class IncorrectPacketException(val expectedIndex: Byte, val payload: ByteArray) : Exception("Invalid payload: ${payload.toHex()}. Expected index: ${expectedIndex}")
|
class IncorrectPacketException(val expectedIndex: Byte, val payload: ByteArray) : Exception("Invalid payload: ${payload.toHex()}. Expected index: $expectedIndex")
|
||||||
|
|
|
@ -21,7 +21,8 @@ data class MessagePacket(
|
||||||
val gateway: Boolean = false,
|
val gateway: Boolean = false,
|
||||||
val sas: Boolean = false, // TODO: understand
|
val sas: Boolean = false, // TODO: understand
|
||||||
val tfs: Boolean = false, // TODO: understand
|
val tfs: Boolean = false, // TODO: understand
|
||||||
val version: Short = 0.toShort()) {
|
val version: Short = 0.toShort()
|
||||||
|
) {
|
||||||
|
|
||||||
fun asByteArray(): ByteArray {
|
fun asByteArray(): ByteArray {
|
||||||
val bb = ByteBuffer.allocate(16 + payload.size)
|
val bb = ByteBuffer.allocate(16 + payload.size)
|
||||||
|
@ -139,7 +140,6 @@ private class Flag(var value: Int = 0) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,6 @@ class PayloadJoiner(private val firstPacket: ByteArray) {
|
||||||
}
|
}
|
||||||
return bytes.copyOfRange(0, bytes.size)
|
return bytes.copyOfRange(0, bytes.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Int.toUnsignedLong() = this.toLong() and 0xffffffffL
|
internal fun Int.toUnsignedLong() = this.toLong() and 0xffffffffL
|
|
@ -15,51 +15,63 @@ internal class PayloadSplitter(private val payload: ByteArray) {
|
||||||
val crc32 = payload.crc32()
|
val crc32 = payload.crc32()
|
||||||
if (payload.size <= FirstBlePacket.CAPACITY_WITH_THE_OPTIONAL_PLUS_ONE_PACKET) {
|
if (payload.size <= FirstBlePacket.CAPACITY_WITH_THE_OPTIONAL_PLUS_ONE_PACKET) {
|
||||||
val end = min(FirstBlePacket.CAPACITY_WITHOUT_MIDDLE_PACKETS, payload.size)
|
val end = min(FirstBlePacket.CAPACITY_WITHOUT_MIDDLE_PACKETS, payload.size)
|
||||||
ret.add(FirstBlePacket(
|
ret.add(
|
||||||
|
FirstBlePacket(
|
||||||
totalFragments = 0,
|
totalFragments = 0,
|
||||||
payload = payload.copyOfRange(0, end),
|
payload = payload.copyOfRange(0, end),
|
||||||
size = payload.size.toByte(),
|
size = payload.size.toByte(),
|
||||||
crc32 = crc32,
|
crc32 = crc32,
|
||||||
))
|
)
|
||||||
|
)
|
||||||
if (payload.size > FirstBlePacket.CAPACITY_WITHOUT_MIDDLE_PACKETS) {
|
if (payload.size > FirstBlePacket.CAPACITY_WITHOUT_MIDDLE_PACKETS) {
|
||||||
ret.add(LastOptionalPlusOneBlePacket(
|
ret.add(
|
||||||
|
LastOptionalPlusOneBlePacket(
|
||||||
index = 1,
|
index = 1,
|
||||||
payload = payload.copyOfRange(end, payload.size),
|
payload = payload.copyOfRange(end, payload.size),
|
||||||
size = (payload.size - end).toByte(),
|
size = (payload.size - end).toByte(),
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
val middleFragments = (payload.size - FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS) / MiddleBlePacket.CAPACITY
|
val middleFragments = (payload.size - FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS) / MiddleBlePacket.CAPACITY
|
||||||
val rest = ((payload.size - middleFragments * MiddleBlePacket.CAPACITY) - FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS).toByte()
|
val rest = ((payload.size - middleFragments * MiddleBlePacket.CAPACITY) - FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS).toByte()
|
||||||
ret.add(FirstBlePacket(
|
ret.add(
|
||||||
|
FirstBlePacket(
|
||||||
totalFragments = (middleFragments + 1).toByte(),
|
totalFragments = (middleFragments + 1).toByte(),
|
||||||
payload = payload.copyOfRange(0, FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS),
|
payload = payload.copyOfRange(0, FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS),
|
||||||
))
|
)
|
||||||
|
)
|
||||||
for (i in 1..middleFragments) {
|
for (i in 1..middleFragments) {
|
||||||
val p = if (i == 1) {
|
val p = if (i == 1) {
|
||||||
payload.copyOfRange(FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS, FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + MiddleBlePacket.CAPACITY)
|
payload.copyOfRange(FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS, FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + MiddleBlePacket.CAPACITY)
|
||||||
} else {
|
} else {
|
||||||
payload.copyOfRange(FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + (i - 1) * MiddleBlePacket.CAPACITY, FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + i * MiddleBlePacket.CAPACITY)
|
payload.copyOfRange(FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + (i - 1) * MiddleBlePacket.CAPACITY, FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + i * MiddleBlePacket.CAPACITY)
|
||||||
}
|
}
|
||||||
ret.add(MiddleBlePacket(
|
ret.add(
|
||||||
|
MiddleBlePacket(
|
||||||
index = i.toByte(),
|
index = i.toByte(),
|
||||||
payload = p,
|
payload = p,
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val end = min(LastBlePacket.CAPACITY, rest.toInt())
|
val end = min(LastBlePacket.CAPACITY, rest.toInt())
|
||||||
ret.add(LastBlePacket(
|
ret.add(
|
||||||
|
LastBlePacket(
|
||||||
index = (middleFragments + 1).toByte(),
|
index = (middleFragments + 1).toByte(),
|
||||||
size = rest,
|
size = rest,
|
||||||
payload = payload.copyOfRange(middleFragments * MiddleBlePacket.CAPACITY + FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS, middleFragments * MiddleBlePacket.CAPACITY + FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + end),
|
payload = payload.copyOfRange(middleFragments * MiddleBlePacket.CAPACITY + FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS, middleFragments * MiddleBlePacket.CAPACITY + FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + end),
|
||||||
crc32 = crc32,
|
crc32 = crc32,
|
||||||
))
|
)
|
||||||
|
)
|
||||||
if (rest > LastBlePacket.CAPACITY) {
|
if (rest > LastBlePacket.CAPACITY) {
|
||||||
ret.add(LastOptionalPlusOneBlePacket(
|
ret.add(
|
||||||
|
LastOptionalPlusOneBlePacket(
|
||||||
index = (middleFragments + 2).toByte(),
|
index = (middleFragments + 2).toByte(),
|
||||||
size = (rest - LastBlePacket.CAPACITY).toByte(),
|
size = (rest - LastBlePacket.CAPACITY).toByte(),
|
||||||
payload = payload.copyOfRange(middleFragments * MiddleBlePacket.CAPACITY + FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + LastBlePacket.CAPACITY, payload.size),
|
payload = payload.copyOfRange(middleFragments * MiddleBlePacket.CAPACITY + FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + LastBlePacket.CAPACITY, payload.size),
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,20 +19,20 @@ class StringLengthPrefixEncoding {
|
||||||
for ((index, key) in keys.withIndex()) {
|
for ((index, key) in keys.withIndex()) {
|
||||||
when {
|
when {
|
||||||
remaining.size < key.length ->
|
remaining.size < key.length ->
|
||||||
throw MessageIOException("Payload too short: ${payload.toHex()} for key: ${key}")
|
throw MessageIOException("Payload too short: ${payload.toHex()} for key: $key")
|
||||||
!(remaining.copyOfRange(0, key.length).decodeToString() == key) ->
|
!(remaining.copyOfRange(0, key.length).decodeToString() == key) ->
|
||||||
throw MessageIOException("Key not found: ${key} in ${payload.toHex()}")
|
throw MessageIOException("Key not found: $key in ${payload.toHex()}")
|
||||||
// last key can be empty, no length
|
// last key can be empty, no length
|
||||||
index == keys.size - 1 && remaining.size == key.length ->
|
index == keys.size - 1 && remaining.size == key.length ->
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
remaining.size < key.length + LENGTH_BYTES ->
|
remaining.size < key.length + LENGTH_BYTES ->
|
||||||
throw MessageIOException("Length not found: for ${key} in ${payload.toHex()}")
|
throw MessageIOException("Length not found: for $key in ${payload.toHex()}")
|
||||||
}
|
}
|
||||||
remaining = remaining.copyOfRange(key.length, remaining.size)
|
remaining = remaining.copyOfRange(key.length, remaining.size)
|
||||||
val length = (remaining[0].toUnsignedInt() shl 1) or remaining[1].toUnsignedInt()
|
val length = (remaining[0].toUnsignedInt() shl 1) or remaining[1].toUnsignedInt()
|
||||||
if (length > remaining.size) {
|
if (length > remaining.size) {
|
||||||
throw MessageIOException("Payload too short, looking for length ${length} for ${key} in ${payload.toHex()}")
|
throw MessageIOException("Payload too short, looking for length $length for $key in ${payload.toHex()}")
|
||||||
}
|
}
|
||||||
ret[index] = remaining.copyOfRange(LENGTH_BYTES, LENGTH_BYTES + length)
|
ret[index] = remaining.copyOfRange(LENGTH_BYTES, LENGTH_BYTES + length)
|
||||||
remaining = remaining.copyOfRange(LENGTH_BYTES + length, remaining.size)
|
remaining = remaining.copyOfRange(LENGTH_BYTES + length, remaining.size)
|
||||||
|
|
|
@ -92,4 +92,3 @@ data class LastOptionalPlusOneBlePacket(val index: Byte, val payload: ByteArray,
|
||||||
internal const val HEADER_SIZE = 2
|
internal const val HEADER_SIZE = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ class BleDiscoveredDevice(val scanResult: ScanResult, private val scanRecord: Sc
|
||||||
val serviceUuids = scanRecord.serviceUuids
|
val serviceUuids = scanRecord.serviceUuids
|
||||||
if (serviceUuids.size != 9) {
|
if (serviceUuids.size != 9) {
|
||||||
throw DiscoveredInvalidPodException("Expected 9 service UUIDs, got" + serviceUuids.size, serviceUuids)
|
throw DiscoveredInvalidPodException("Expected 9 service UUIDs, got" + serviceUuids.size, serviceUuids)
|
||||||
|
|
||||||
}
|
}
|
||||||
if (extractUUID16(serviceUuids[0]) != MAIN_SERVICE_UUID) {
|
if (extractUUID16(serviceUuids[0]) != MAIN_SERVICE_UUID) {
|
||||||
// this is the service that we filtered for
|
// this is the service that we filtered for
|
||||||
|
|
|
@ -45,5 +45,4 @@ class ScanCollector(private val logger: AAPSLogger, private val podID: Long) : S
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableList(ret)
|
return Collections.unmodifiableList(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -20,4 +20,3 @@ sealed class PodEvent {
|
||||||
class CommandSent(val command: Command) : PodEvent()
|
class CommandSent(val command: Command) : PodEvent()
|
||||||
class ResponseReceived(val response: Response) : PodEvent()
|
class ResponseReceived(val response: Response) : PodEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,14 @@ class DeactivateCommand private constructor(
|
||||||
) : NonceEnabledCommand(CommandType.DEACTIVATE, uniqueId, sequenceNumber, multiCommandFlag, nonce) {
|
) : NonceEnabledCommand(CommandType.DEACTIVATE, uniqueId, sequenceNumber, multiCommandFlag, nonce) {
|
||||||
|
|
||||||
override val encoded: ByteArray
|
override val encoded: ByteArray
|
||||||
get() = appendCrc(ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
get() = appendCrc(
|
||||||
|
ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
||||||
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
||||||
.put(commandType.value) //
|
.put(commandType.value) //
|
||||||
.put(BODY_LENGTH) //
|
.put(BODY_LENGTH) //
|
||||||
.putInt(nonce) //
|
.putInt(nonce) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
|
|
||||||
override fun toString(): String = "DeactivateCommand{" +
|
override fun toString(): String = "DeactivateCommand{" +
|
||||||
"nonce=" + nonce +
|
"nonce=" + nonce +
|
||||||
|
|
|
@ -14,12 +14,14 @@ class GetStatusCommand private constructor(
|
||||||
) : HeaderEnabledCommand(CommandType.GET_STATUS, uniqueId, sequenceNumber, multiCommandFlag) {
|
) : HeaderEnabledCommand(CommandType.GET_STATUS, uniqueId, sequenceNumber, multiCommandFlag) {
|
||||||
|
|
||||||
override val encoded: ByteArray
|
override val encoded: ByteArray
|
||||||
get() = appendCrc(ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
get() = appendCrc(
|
||||||
|
ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
||||||
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
||||||
.put(commandType.value) //
|
.put(commandType.value) //
|
||||||
.put(BODY_LENGTH) //
|
.put(BODY_LENGTH) //
|
||||||
.put(statusResponseType.value) //
|
.put(statusResponseType.value) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
|
|
||||||
class Builder : HeaderEnabledCommandBuilder<Builder, GetStatusCommand>() {
|
class Builder : HeaderEnabledCommandBuilder<Builder, GetStatusCommand>() {
|
||||||
|
|
||||||
|
@ -35,7 +37,6 @@ class GetStatusCommand private constructor(
|
||||||
|
|
||||||
return GetStatusCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, statusResponseType!!)
|
return GetStatusCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, statusResponseType!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -12,12 +12,14 @@ class GetVersionCommand private constructor(
|
||||||
) : HeaderEnabledCommand(CommandType.GET_VERSION, uniqueId, sequenceNumber, multiCommandFlag) {
|
) : HeaderEnabledCommand(CommandType.GET_VERSION, uniqueId, sequenceNumber, multiCommandFlag) {
|
||||||
|
|
||||||
override val encoded: ByteArray
|
override val encoded: ByteArray
|
||||||
get() = appendCrc(ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
get() = appendCrc(
|
||||||
|
ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
||||||
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
||||||
.put(commandType.value) //
|
.put(commandType.value) //
|
||||||
.put(BODY_LENGTH) //
|
.put(BODY_LENGTH) //
|
||||||
.putInt(uniqueId) //
|
.putInt(uniqueId) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "GetVersionCommand{" +
|
return "GetVersionCommand{" +
|
||||||
|
|
|
@ -49,11 +49,13 @@ class ProgramBasalCommand private constructor(
|
||||||
val basalCommand = buffer.array()
|
val basalCommand = buffer.array()
|
||||||
val interlockCommand = interlockCommand.encoded
|
val interlockCommand = interlockCommand.encoded
|
||||||
val header: ByteArray = encodeHeader(uniqueId, sequenceNumber, (basalCommand.size + interlockCommand.size).toShort(), multiCommandFlag)
|
val header: ByteArray = encodeHeader(uniqueId, sequenceNumber, (basalCommand.size + interlockCommand.size).toShort(), multiCommandFlag)
|
||||||
return appendCrc(ByteBuffer.allocate(basalCommand.size + interlockCommand.size + header.size) //
|
return appendCrc(
|
||||||
|
ByteBuffer.allocate(basalCommand.size + interlockCommand.size + header.size) //
|
||||||
.put(header) //
|
.put(header) //
|
||||||
.put(interlockCommand) //
|
.put(interlockCommand) //
|
||||||
.put(basalCommand) //
|
.put(basalCommand) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
@ -102,12 +104,16 @@ class ProgramBasalCommand private constructor(
|
||||||
val longInsulinProgramElements: List<BasalInsulinProgramElement> = mapTenthPulsesPerSlotToLongInsulinProgramElements(ProgramBasalUtil.mapBasalProgramToTenthPulsesPerSlot(basalProgram!!))
|
val longInsulinProgramElements: List<BasalInsulinProgramElement> = mapTenthPulsesPerSlotToLongInsulinProgramElements(ProgramBasalUtil.mapBasalProgramToTenthPulsesPerSlot(basalProgram!!))
|
||||||
val shortInsulinProgramElements = ProgramBasalUtil.mapPulsesPerSlotToShortInsulinProgramElements(pulsesPerSlot)
|
val shortInsulinProgramElements = ProgramBasalUtil.mapPulsesPerSlotToShortInsulinProgramElements(pulsesPerSlot)
|
||||||
val currentBasalInsulinProgramElement = ProgramBasalUtil.calculateCurrentLongInsulinProgramElement(longInsulinProgramElements, currentTime)
|
val currentBasalInsulinProgramElement = ProgramBasalUtil.calculateCurrentLongInsulinProgramElement(longInsulinProgramElements, currentTime)
|
||||||
val interlockCommand = ProgramInsulinCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, nonce!!,
|
val interlockCommand = ProgramInsulinCommand(
|
||||||
|
uniqueId!!, sequenceNumber!!, multiCommandFlag, nonce!!,
|
||||||
shortInsulinProgramElements, checksum, currentSlot.index, currentSlot.eighthSecondsRemaining,
|
shortInsulinProgramElements, checksum, currentSlot.index, currentSlot.eighthSecondsRemaining,
|
||||||
currentSlot.pulsesRemaining, ProgramInsulinCommand.DeliveryType.BASAL)
|
currentSlot.pulsesRemaining, ProgramInsulinCommand.DeliveryType.BASAL
|
||||||
return ProgramBasalCommand(interlockCommand, uniqueId!!, sequenceNumber!!, multiCommandFlag,
|
)
|
||||||
|
return ProgramBasalCommand(
|
||||||
|
interlockCommand, uniqueId!!, sequenceNumber!!, multiCommandFlag,
|
||||||
longInsulinProgramElements, programReminder!!, currentBasalInsulinProgramElement.index,
|
longInsulinProgramElements, programReminder!!, currentBasalInsulinProgramElement.index,
|
||||||
currentBasalInsulinProgramElement.remainingTenthPulses, currentBasalInsulinProgramElement.delayUntilNextTenthPulseInUsec)
|
currentBasalInsulinProgramElement.remainingTenthPulses, currentBasalInsulinProgramElement.delayUntilNextTenthPulseInUsec
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@ class ProgramBeepsCommand private constructor(
|
||||||
) : HeaderEnabledCommand(CommandType.PROGRAM_BEEPS, uniqueId, sequenceNumber, multiCommandFlag) {
|
) : HeaderEnabledCommand(CommandType.PROGRAM_BEEPS, uniqueId, sequenceNumber, multiCommandFlag) {
|
||||||
|
|
||||||
override val encoded: ByteArray
|
override val encoded: ByteArray
|
||||||
get() = appendCrc(ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
get() = appendCrc(
|
||||||
|
ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
||||||
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
||||||
.put(commandType.value) //
|
.put(commandType.value) //
|
||||||
.put(BODY_LENGTH) //
|
.put(BODY_LENGTH) //
|
||||||
|
@ -26,7 +27,8 @@ class ProgramBeepsCommand private constructor(
|
||||||
.put(basalReminder.encoded) //
|
.put(basalReminder.encoded) //
|
||||||
.put(tempBasalReminder.encoded) //
|
.put(tempBasalReminder.encoded) //
|
||||||
.put(bolusReminder.encoded) //
|
.put(bolusReminder.encoded) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
|
|
||||||
class Builder : HeaderEnabledCommandBuilder<Builder, ProgramBeepsCommand>() {
|
class Builder : HeaderEnabledCommandBuilder<Builder, ProgramBeepsCommand>() {
|
||||||
|
|
||||||
|
|
|
@ -32,11 +32,13 @@ class ProgramBolusCommand private constructor(
|
||||||
.array()
|
.array()
|
||||||
val interlockCommand = interlockCommand.encoded
|
val interlockCommand = interlockCommand.encoded
|
||||||
val header: ByteArray = encodeHeader(uniqueId, sequenceNumber, (bolusCommand.size + interlockCommand.size).toShort(), multiCommandFlag)
|
val header: ByteArray = encodeHeader(uniqueId, sequenceNumber, (bolusCommand.size + interlockCommand.size).toShort(), multiCommandFlag)
|
||||||
return appendCrc(ByteBuffer.allocate(header.size + interlockCommand.size + bolusCommand.size) //
|
return appendCrc(
|
||||||
|
ByteBuffer.allocate(header.size + interlockCommand.size + bolusCommand.size) //
|
||||||
.put(header) //
|
.put(header) //
|
||||||
.put(interlockCommand) //
|
.put(interlockCommand) //
|
||||||
.put(bolusCommand) //
|
.put(bolusCommand) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
@ -82,8 +84,10 @@ class ProgramBolusCommand private constructor(
|
||||||
|
|
||||||
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(
|
||||||
0x01.toByte(), byte10And11, numberOfPulses, ProgramInsulinCommand.DeliveryType.BOLUS)
|
uniqueId!!, sequenceNumber!!, multiCommandFlag, nonce!!, listOf(BolusShortInsulinProgramElement(numberOfPulses)), calculateChecksum(0x01.toByte(), byte10And11, numberOfPulses),
|
||||||
|
0x01.toByte(), byte10And11, numberOfPulses, ProgramInsulinCommand.DeliveryType.BOLUS
|
||||||
|
)
|
||||||
val delayUntilFirstTenthPulseInUsec = delayBetweenPulsesInEighthSeconds!! / 8 * 100000
|
val delayUntilFirstTenthPulseInUsec = delayBetweenPulsesInEighthSeconds!! / 8 * 100000
|
||||||
return ProgramBolusCommand(interlockCommand, uniqueId!!, sequenceNumber!!, multiCommandFlag, programReminder!!, (numberOfPulses * 10).toShort(), delayUntilFirstTenthPulseInUsec)
|
return ProgramBolusCommand(interlockCommand, uniqueId!!, sequenceNumber!!, multiCommandFlag, programReminder!!, (numberOfPulses * 10).toShort(), delayUntilFirstTenthPulseInUsec)
|
||||||
}
|
}
|
||||||
|
@ -94,12 +98,14 @@ class ProgramBolusCommand private constructor(
|
||||||
private const val LENGTH: Short = 15
|
private const val LENGTH: Short = 15
|
||||||
private const val BODY_LENGTH: Byte = 13
|
private const val BODY_LENGTH: Byte = 13
|
||||||
private fun calculateChecksum(numberOfSlots: Byte, byte10And11: Short, numberOfPulses: Short): Short {
|
private fun calculateChecksum(numberOfSlots: Byte, byte10And11: Short, numberOfPulses: Short): Short {
|
||||||
return MessageUtil.calculateChecksum(ByteBuffer.allocate(7) //
|
return MessageUtil.calculateChecksum(
|
||||||
|
ByteBuffer.allocate(7) //
|
||||||
.put(numberOfSlots) //
|
.put(numberOfSlots) //
|
||||||
.putShort(byte10And11) //
|
.putShort(byte10And11) //
|
||||||
.putShort(numberOfPulses) //
|
.putShort(numberOfPulses) //
|
||||||
.putShort(numberOfPulses) //
|
.putShort(numberOfPulses) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,7 +11,8 @@ class ProgramInsulinCommand internal constructor(
|
||||||
uniqueId: Int,
|
uniqueId: Int,
|
||||||
sequenceNumber: Short,
|
sequenceNumber: Short,
|
||||||
multiCommandFlag: Boolean,
|
multiCommandFlag: Boolean,
|
||||||
nonce: Int, insulinProgramElements:
|
nonce: Int,
|
||||||
|
insulinProgramElements:
|
||||||
List<ShortInsulinProgramElement>,
|
List<ShortInsulinProgramElement>,
|
||||||
private val checksum: Short,
|
private val checksum: Short,
|
||||||
private val byte9: Byte,
|
private val byte9: Byte,
|
||||||
|
|
|
@ -59,9 +59,11 @@ class ProgramTempBasalCommand private constructor(
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,10 +93,12 @@ class ProgramTempBasalCommand private 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) //
|
||||||
.put(tempBasalCommand) //
|
.put(tempBasalCommand) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,8 @@ class SetUniqueIdCommand private constructor(
|
||||||
) : HeaderEnabledCommand(CommandType.SET_UNIQUE_ID, uniqueId, sequenceNumber, multiCommandFlag) {
|
) : HeaderEnabledCommand(CommandType.SET_UNIQUE_ID, uniqueId, sequenceNumber, multiCommandFlag) {
|
||||||
|
|
||||||
override val encoded: ByteArray
|
override val encoded: ByteArray
|
||||||
get() = appendCrc(ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
get() = appendCrc(
|
||||||
|
ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
||||||
.put(encodeHeader(DEFAULT_UNIQUE_ID, sequenceNumber, LENGTH, multiCommandFlag)) //
|
.put(encodeHeader(DEFAULT_UNIQUE_ID, sequenceNumber, LENGTH, multiCommandFlag)) //
|
||||||
.put(commandType.value) //
|
.put(commandType.value) //
|
||||||
.put(BODY_LENGTH) //
|
.put(BODY_LENGTH) //
|
||||||
|
@ -26,7 +27,8 @@ class SetUniqueIdCommand private constructor(
|
||||||
.put(encodeInitializationTime(initializationTime)) //
|
.put(encodeInitializationTime(initializationTime)) //
|
||||||
.putInt(lotNumber) //
|
.putInt(lotNumber) //
|
||||||
.putInt(podSequenceNumber) //
|
.putInt(podSequenceNumber) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "SetUniqueIdCommand{" +
|
return "SetUniqueIdCommand{" +
|
||||||
|
|
|
@ -18,13 +18,15 @@ class SilenceAlertsCommand private constructor(
|
||||||
|
|
||||||
override val encoded: ByteArray
|
override val encoded: ByteArray
|
||||||
get() =
|
get() =
|
||||||
appendCrc(ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
appendCrc(
|
||||||
|
ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
||||||
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
||||||
.put(commandType.value) //
|
.put(commandType.value) //
|
||||||
.put(BODY_LENGTH) //
|
.put(BODY_LENGTH) //
|
||||||
.putInt(nonce) //
|
.putInt(nonce) //
|
||||||
.put(AlertUtil.encodeAlertSet(alertTypes)) //
|
.put(AlertUtil.encodeAlertSet(alertTypes)) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "SilenceAlertsCommand{" +
|
return "SilenceAlertsCommand{" +
|
||||||
|
|
|
@ -19,13 +19,15 @@ class StopDeliveryCommand private constructor(
|
||||||
|
|
||||||
override val encoded: ByteArray
|
override val encoded: ByteArray
|
||||||
get() {
|
get() {
|
||||||
return appendCrc(ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
return appendCrc(
|
||||||
|
ByteBuffer.allocate(LENGTH + HEADER_LENGTH) //
|
||||||
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
.put(encodeHeader(uniqueId, sequenceNumber, LENGTH, multiCommandFlag)) //
|
||||||
.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()) //
|
.put((beepType.value.toInt() shl 4 or deliveryType.encoded[0].toInt()).toByte()) //
|
||||||
.array())
|
.array()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|
|
@ -11,9 +11,11 @@ class BasalShortInsulinProgramElement(
|
||||||
|
|
||||||
override val encoded: ByteArray
|
override val encoded: ByteArray
|
||||||
get() {
|
get() {
|
||||||
val firstByte = (numberOfSlots - 1 and 0x0f shl 4 //
|
val firstByte = (
|
||||||
|
numberOfSlots - 1 and 0x0f shl 4 //
|
||||||
or ((if (extraAlternatePulse) 1 else 0) shl 3) //
|
or ((if (extraAlternatePulse) 1 else 0) shl 3) //
|
||||||
or (pulsesPerSlot.toInt() ushr 8 and 0x03)).toByte()
|
or (pulsesPerSlot.toInt() ushr 8 and 0x03)
|
||||||
|
).toByte()
|
||||||
return ByteBuffer.allocate(2) //
|
return ByteBuffer.allocate(2) //
|
||||||
.put(firstByte) //
|
.put(firstByte) //
|
||||||
.put((pulsesPerSlot and 0xff).toByte()) //
|
.put((pulsesPerSlot and 0xff).toByte()) //
|
||||||
|
|
|
@ -159,5 +159,4 @@ enum class AlarmType(override val value: Byte) : HasValue {
|
||||||
ALARM_BLE_QN_EXCEED_MAX_RETRY(0xc1.toByte()),
|
ALARM_BLE_QN_EXCEED_MAX_RETRY(0xc1.toByte()),
|
||||||
ALARM_BLE_QN_CRIT_VAR_FAIL(0xc2.toByte()),
|
ALARM_BLE_QN_CRIT_VAR_FAIL(0xc2.toByte()),
|
||||||
UNKNOWN(0xff.toByte());
|
UNKNOWN(0xff.toByte());
|
||||||
|
|
||||||
}
|
}
|
|
@ -29,7 +29,8 @@ class AlertConfiguration(
|
||||||
return ByteBuffer.allocate(6) //
|
return ByteBuffer.allocate(6) //
|
||||||
.put(firstByte)
|
.put(firstByte)
|
||||||
.put(durationInMinutes.toByte()) //
|
.put(durationInMinutes.toByte()) //
|
||||||
.putShort(when (trigger) {
|
.putShort(
|
||||||
|
when (trigger) {
|
||||||
is AlertTrigger.ReservoirVolumeTrigger -> {
|
is AlertTrigger.ReservoirVolumeTrigger -> {
|
||||||
trigger.thresholdInMicroLiters
|
trigger.thresholdInMicroLiters
|
||||||
}
|
}
|
||||||
|
@ -37,7 +38,8 @@ class AlertConfiguration(
|
||||||
is AlertTrigger.TimerTrigger -> {
|
is AlertTrigger.TimerTrigger -> {
|
||||||
trigger.offsetInMinutes
|
trigger.offsetInMinutes
|
||||||
}
|
}
|
||||||
}) //
|
}
|
||||||
|
) //
|
||||||
.put(beepRepetition.value) //
|
.put(beepRepetition.value) //
|
||||||
.put(beepType.value) //
|
.put(beepType.value) //
|
||||||
.array()
|
.array()
|
||||||
|
|
|
@ -10,5 +10,4 @@ enum class BeepRepetitionType(
|
||||||
XXX3(0x05.toByte()), // Used in user pod expiration alert
|
XXX3(0x05.toByte()), // Used in user pod expiration alert
|
||||||
XXX4(0x06.toByte()), // Used in pod expiration alert
|
XXX4(0x06.toByte()), // Used in pod expiration alert
|
||||||
XXX5(0x08.toByte()); // Used in imminent pod expiration alert
|
XXX5(0x08.toByte()); // Used in imminent pod expiration alert
|
||||||
|
|
||||||
}
|
}
|
|
@ -10,7 +10,11 @@ class ProgramReminder(
|
||||||
) : Encodable, Serializable {
|
) : Encodable, Serializable {
|
||||||
|
|
||||||
override val encoded: ByteArray
|
override val encoded: ByteArray
|
||||||
get() = byteArrayOf(((if (atStart) 1 else 0) shl 7
|
get() = byteArrayOf(
|
||||||
|
(
|
||||||
|
(if (atStart) 1 else 0) shl 7
|
||||||
or ((if (atEnd) 1 else 0) shl 6)
|
or ((if (atEnd) 1 else 0) shl 6)
|
||||||
or ((atInterval and 0x3f).toInt())).toByte())
|
or ((atInterval and 0x3f).toInt())
|
||||||
|
).toByte()
|
||||||
|
)
|
||||||
}
|
}
|
|
@ -84,5 +84,4 @@ class AlarmStatusResponse(
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Byte.shr(i: Int): Int = toInt() shr i
|
infix fun Byte.shr(i: Int): Int = toInt() shr i
|
||||||
|
|
||||||
}
|
}
|
|
@ -34,7 +34,6 @@ class DefaultStatusResponse(
|
||||||
", minutesSinceActivation=$minutesSinceActivation" +
|
", minutesSinceActivation=$minutesSinceActivation" +
|
||||||
", reservoirPulsesRemaining=$reservoirPulsesRemaining)"
|
", reservoirPulsesRemaining=$reservoirPulsesRemaining)"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Byte.ushr(i: Int) = toInt() ushr i
|
infix fun Byte.ushr(i: Int) = toInt() ushr i
|
||||||
|
|
|
@ -6,5 +6,4 @@ abstract class ResponseBase(
|
||||||
) : Response {
|
) : Response {
|
||||||
|
|
||||||
override val encoded: ByteArray = encoded.copyOf(encoded.size)
|
override val encoded: ByteArray = encoded.copyOf(encoded.size)
|
||||||
|
|
||||||
}
|
}
|
|
@ -55,5 +55,4 @@ class SetUniqueIdResponse(
|
||||||
", encoded=" + encoded.contentToString() +
|
", encoded=" + encoded.contentToString() +
|
||||||
'}'
|
'}'
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -49,5 +49,4 @@ class VersionResponse(
|
||||||
", encoded=" + Arrays.toString(encoded) +
|
", encoded=" + Arrays.toString(encoded) +
|
||||||
'}'
|
'}'
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -20,7 +20,8 @@ object AlertUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun encodeAlertSet(alertSet: EnumSet<AlertType>): Byte =
|
fun encodeAlertSet(alertSet: EnumSet<AlertType>): Byte =
|
||||||
alertSet.fold(0,
|
alertSet.fold(
|
||||||
|
0,
|
||||||
{ out, slot ->
|
{ out, slot ->
|
||||||
out or (slot.value.toInt() and 0xff)
|
out or (slot.value.toInt() and 0xff)
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,8 @@ class DashHistory @Inject constructor(
|
||||||
return Single.error(IllegalArgumentException("tempBasalRecord missing on SET_TEMPORARY_BASAL"))
|
return Single.error(IllegalArgumentException("tempBasalRecord missing on SET_TEMPORARY_BASAL"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return dao.save(HistoryRecordEntity(
|
return dao.save(
|
||||||
|
HistoryRecordEntity(
|
||||||
id = id,
|
id = id,
|
||||||
date = date,
|
date = date,
|
||||||
createdAt = currentTimeMillis(),
|
createdAt = currentTimeMillis(),
|
||||||
|
@ -53,7 +54,8 @@ class DashHistory @Inject constructor(
|
||||||
bolusRecord = bolusRecord,
|
bolusRecord = bolusRecord,
|
||||||
initialResult = initialResult,
|
initialResult = initialResult,
|
||||||
resolvedResult = resolveResult,
|
resolvedResult = resolveResult,
|
||||||
resolvedAt = resolvedAt)
|
resolvedAt = resolvedAt
|
||||||
|
)
|
||||||
).toSingle { id }
|
).toSingle { id }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,5 +63,4 @@ class DashHistory @Inject constructor(
|
||||||
dao.all().map { list -> list.map(historyMapper::entityToDomain) }
|
dao.all().map { list -> list.map(historyMapper::entityToDomain) }
|
||||||
|
|
||||||
fun getRecordsAfter(time: Long): Single<List<HistoryRecordEntity>> = dao.allSince(time)
|
fun getRecordsAfter(time: Long): Single<List<HistoryRecordEntity>> = dao.allSince(time)
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,7 +5,6 @@ import androidx.room.Database
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.TypeConverters
|
import androidx.room.TypeConverters
|
||||||
import androidx.room.migration.Migration
|
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
entities = [HistoryRecordEntity::class],
|
entities = [HistoryRecordEntity::class],
|
||||||
|
@ -26,5 +25,4 @@ abstract class DashHistoryDatabase : RoomDatabase() {
|
||||||
.fallbackToDestructiveMigration()
|
.fallbackToDestructiveMigration()
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -32,5 +32,4 @@ abstract class HistoryRecordDao {
|
||||||
|
|
||||||
@Query("UPDATE historyrecords SET resolvedResult = :resolvedResult, resolvedAt = :resolvedAt WHERE id = :id ")
|
@Query("UPDATE historyrecords SET resolvedResult = :resolvedResult, resolvedAt = :resolvedAt WHERE id = :id ")
|
||||||
abstract fun markResolved(id: String, resolvedResult: ResolvedResult, resolvedAt: Long): Completable
|
abstract fun markResolved(id: String, resolvedResult: ResolvedResult, resolvedAt: Long): Completable
|
||||||
|
|
||||||
}
|
}
|
|
@ -19,5 +19,5 @@ data class HistoryRecordEntity(
|
||||||
@Embedded(prefix = "tempBasalRecord_") val tempBasalRecord: TempBasalRecord?,
|
@Embedded(prefix = "tempBasalRecord_") val tempBasalRecord: TempBasalRecord?,
|
||||||
@Embedded(prefix = "bolusRecord_") val bolusRecord: BolusRecord?,
|
@Embedded(prefix = "bolusRecord_") val bolusRecord: BolusRecord?,
|
||||||
val resolvedResult: ResolvedResult?,
|
val resolvedResult: ResolvedResult?,
|
||||||
val resolvedAt: Long?)
|
val resolvedAt: Long?
|
||||||
|
)
|
||||||
|
|
|
@ -21,7 +21,8 @@ class HistoryMapper {
|
||||||
)
|
)
|
||||||
|
|
||||||
fun entityToDomain(entity: HistoryRecordEntity): HistoryRecord =
|
fun entityToDomain(entity: HistoryRecordEntity): HistoryRecord =
|
||||||
HistoryRecord(id = entity.id,
|
HistoryRecord(
|
||||||
|
id = entity.id,
|
||||||
createdAt = entity.createdAt,
|
createdAt = entity.createdAt,
|
||||||
date = entity.date,
|
date = entity.date,
|
||||||
initialResult = entity.initialResult,
|
initialResult = entity.initialResult,
|
||||||
|
@ -30,5 +31,4 @@ class HistoryMapper {
|
||||||
resolvedResult = entity.resolvedResult,
|
resolvedResult = entity.resolvedResult,
|
||||||
resolvedAt = entity.resolvedAt
|
resolvedAt = entity.resolvedAt
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
|
@ -66,10 +66,13 @@ class DashPodManagementActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.buttonDiscardPod.setOnClickListener {
|
binding.buttonDiscardPod.setOnClickListener {
|
||||||
OKDialog.showConfirmation(this,
|
OKDialog.showConfirmation(
|
||||||
resourceHelper.gs(R.string.omnipod_common_pod_management_discard_pod_confirmation), Thread {
|
this,
|
||||||
|
resourceHelper.gs(R.string.omnipod_common_pod_management_discard_pod_confirmation),
|
||||||
|
Thread {
|
||||||
// TODO discard Pod
|
// TODO discard Pod
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.buttonPlayTestBeep.setOnClickListener {
|
binding.buttonPlayTestBeep.setOnClickListener {
|
||||||
|
@ -77,13 +80,16 @@ class DashPodManagementActivity : NoSplashAppCompatActivity() {
|
||||||
binding.buttonPlayTestBeep.isEnabled = false
|
binding.buttonPlayTestBeep.isEnabled = false
|
||||||
binding.buttonPlayTestBeep.setText(R.string.omnipod_common_pod_management_button_playing_test_beep)
|
binding.buttonPlayTestBeep.setText(R.string.omnipod_common_pod_management_button_playing_test_beep)
|
||||||
|
|
||||||
commandQueue.customCommand(CommandPlayTestBeep(), object : Callback() {
|
commandQueue.customCommand(
|
||||||
|
CommandPlayTestBeep(),
|
||||||
|
object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
displayErrorDialog(resourceHelper.gs(R.string.omnipod_common_warning), resourceHelper.gs(R.string.omnipod_common_two_strings_concatenated_by_colon, resourceHelper.gs(R.string.omnipod_common_error_failed_to_play_test_beep), result.comment), false)
|
displayErrorDialog(resourceHelper.gs(R.string.omnipod_common_warning), resourceHelper.gs(R.string.omnipod_common_two_strings_concatenated_by_colon, resourceHelper.gs(R.string.omnipod_common_error_failed_to_play_test_beep), result.comment), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,38 +107,47 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
||||||
|
|
||||||
buttonBinding.buttonResumeDelivery.setOnClickListener {
|
buttonBinding.buttonResumeDelivery.setOnClickListener {
|
||||||
disablePodActionButtons()
|
disablePodActionButtons()
|
||||||
commandQueue.customCommand(CommandResumeDelivery(),
|
commandQueue.customCommand(
|
||||||
DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_common_error_failed_to_resume_delivery), true).messageOnSuccess(resourceHelper.gs(R.string.omnipod_common_confirmation_delivery_resumed)))
|
CommandResumeDelivery(),
|
||||||
|
DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_common_error_failed_to_resume_delivery), true).messageOnSuccess(resourceHelper.gs(R.string.omnipod_common_confirmation_delivery_resumed))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonBinding.buttonRefreshStatus.setOnClickListener {
|
buttonBinding.buttonRefreshStatus.setOnClickListener {
|
||||||
disablePodActionButtons()
|
disablePodActionButtons()
|
||||||
commandQueue.readStatus("REQUESTED BY USER",
|
commandQueue.readStatus(
|
||||||
DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_common_error_failed_to_refresh_status), false))
|
"REQUESTED BY USER",
|
||||||
|
DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_common_error_failed_to_refresh_status), false)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonBinding.buttonSilenceAlerts.setOnClickListener {
|
buttonBinding.buttonSilenceAlerts.setOnClickListener {
|
||||||
disablePodActionButtons()
|
disablePodActionButtons()
|
||||||
commandQueue.customCommand(CommandAcknowledgeAlerts(),
|
commandQueue.customCommand(
|
||||||
|
CommandAcknowledgeAlerts(),
|
||||||
DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_common_error_failed_to_silence_alerts), false)
|
DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_common_error_failed_to_silence_alerts), false)
|
||||||
.messageOnSuccess(resourceHelper.gs(R.string.omnipod_common_confirmation_silenced_alerts))
|
.messageOnSuccess(resourceHelper.gs(R.string.omnipod_common_confirmation_silenced_alerts))
|
||||||
.actionOnSuccess { rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_ALERTS)) })
|
.actionOnSuccess { rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_ALERTS)) }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonBinding.buttonSuspendDelivery.setOnClickListener {
|
buttonBinding.buttonSuspendDelivery.setOnClickListener {
|
||||||
disablePodActionButtons()
|
disablePodActionButtons()
|
||||||
commandQueue.customCommand(CommandSuspendDelivery(),
|
commandQueue.customCommand(
|
||||||
|
CommandSuspendDelivery(),
|
||||||
DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_common_error_failed_to_suspend_delivery), true)
|
DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_common_error_failed_to_suspend_delivery), true)
|
||||||
.messageOnSuccess(resourceHelper.gs(R.string.omnipod_common_confirmation_suspended_delivery)))
|
.messageOnSuccess(resourceHelper.gs(R.string.omnipod_common_confirmation_suspended_delivery))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonBinding.buttonSetTime.setOnClickListener {
|
buttonBinding.buttonSetTime.setOnClickListener {
|
||||||
disablePodActionButtons()
|
disablePodActionButtons()
|
||||||
commandQueue.customCommand(CommandHandleTimeChange(true),
|
commandQueue.customCommand(
|
||||||
|
CommandHandleTimeChange(true),
|
||||||
DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_common_error_failed_to_set_time), true)
|
DisplayResultDialogCallback(resourceHelper.gs(R.string.omnipod_common_error_failed_to_set_time), true)
|
||||||
.messageOnSuccess(resourceHelper.gs(R.string.omnipod_common_confirmation_time_on_pod_updated)))
|
.messageOnSuccess(resourceHelper.gs(R.string.omnipod_common_confirmation_time_on_pod_updated))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
@ -147,23 +156,32 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
||||||
disposables += rxBus
|
disposables += rxBus
|
||||||
.toObservable(EventOmnipodDashPumpValuesChanged::class.java)
|
.toObservable(EventOmnipodDashPumpValuesChanged::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe(
|
||||||
|
{
|
||||||
updateOmnipodStatus()
|
updateOmnipodStatus()
|
||||||
updatePodActionButtons()
|
updatePodActionButtons()
|
||||||
}, fabricPrivacy::logException)
|
},
|
||||||
|
fabricPrivacy::logException
|
||||||
|
)
|
||||||
disposables += rxBus
|
disposables += rxBus
|
||||||
.toObservable(EventQueueChanged::class.java)
|
.toObservable(EventQueueChanged::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe(
|
||||||
|
{
|
||||||
updateQueueStatus()
|
updateQueueStatus()
|
||||||
updatePodActionButtons()
|
updatePodActionButtons()
|
||||||
}, fabricPrivacy::logException)
|
},
|
||||||
|
fabricPrivacy::logException
|
||||||
|
)
|
||||||
disposables += rxBus
|
disposables += rxBus
|
||||||
.toObservable(EventPreferenceChange::class.java)
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe(
|
||||||
|
{
|
||||||
updatePodActionButtons()
|
updatePodActionButtons()
|
||||||
}, fabricPrivacy::logException)
|
},
|
||||||
|
fabricPrivacy::logException
|
||||||
|
)
|
||||||
updateUi()
|
updateUi()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,11 +290,13 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
||||||
val lowReservoirThreshold: Short = 20
|
val lowReservoirThreshold: Short = 20
|
||||||
|
|
||||||
podInfoBinding.reservoir.text = resourceHelper.gs(R.string.omnipod_common_overview_reservoir_value, podStateManager.pulsesRemaining)
|
podInfoBinding.reservoir.text = resourceHelper.gs(R.string.omnipod_common_overview_reservoir_value, podStateManager.pulsesRemaining)
|
||||||
podInfoBinding.reservoir.setTextColor(if (podStateManager.pulsesRemaining!! < lowReservoirThreshold) {
|
podInfoBinding.reservoir.setTextColor(
|
||||||
|
if (podStateManager.pulsesRemaining!! < lowReservoirThreshold) {
|
||||||
Color.RED
|
Color.RED
|
||||||
} else {
|
} else {
|
||||||
Color.WHITE
|
Color.WHITE
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
podInfoBinding.podActiveAlerts.text = if (podStateManager.activeAlerts!!.size > 0) {
|
podInfoBinding.podActiveAlerts.text = if (podStateManager.activeAlerts!!.size > 0) {
|
||||||
|
@ -417,8 +437,8 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateRefreshStatusButton() {
|
private fun updateRefreshStatusButton() {
|
||||||
buttonBinding.buttonRefreshStatus.isEnabled = podStateManager.isUniqueIdSet && podStateManager.activationProgress.isAtLeast(ActivationProgress.PHASE_1_COMPLETED)
|
buttonBinding.buttonRefreshStatus.isEnabled = podStateManager.isUniqueIdSet && podStateManager.activationProgress.isAtLeast(ActivationProgress.PHASE_1_COMPLETED) &&
|
||||||
&& isQueueEmpty()
|
isQueueEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateResumeDeliveryButton() {
|
private fun updateResumeDeliveryButton() {
|
||||||
|
@ -576,5 +596,4 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -12,5 +12,4 @@ class DashPodDeactivatedViewModel @Inject constructor() : PodDeactivatedViewMode
|
||||||
|
|
||||||
@StringRes
|
@StringRes
|
||||||
override fun getTextId() = R.string.omnipod_common_pod_deactivation_wizard_pod_deactivated_text
|
override fun getTextId() = R.string.omnipod_common_pod_deactivation_wizard_pod_deactivated_text
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command
|
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command
|
||||||
|
|
||||||
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.AlertType
|
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertTrigger
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertTrigger
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepRepetitionType
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepRepetitionType
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepType
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.BeepType
|
||||||
import org.apache.commons.codec.DecoderException
|
import org.apache.commons.codec.DecoderException
|
||||||
|
|
|
@ -3,7 +3,6 @@ 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.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
|
||||||
|
|
|
@ -26,11 +26,13 @@ class FunctionsTest {
|
||||||
val value3 = Mockito.mock(ProfileValue::class.java)
|
val value3 = Mockito.mock(ProfileValue::class.java)
|
||||||
value3.timeAsSeconds = 50400
|
value3.timeAsSeconds = 50400
|
||||||
value3.value = 3.05
|
value3.value = 3.05
|
||||||
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOf(
|
PowerMockito.`when`(profile.basalValues).thenReturn(
|
||||||
|
arrayOf(
|
||||||
value1,
|
value1,
|
||||||
value2,
|
value2,
|
||||||
value3
|
value3
|
||||||
))
|
)
|
||||||
|
)
|
||||||
val basalProgram: BasalProgram = mapProfileToBasalProgram(profile)
|
val basalProgram: BasalProgram = mapProfileToBasalProgram(profile)
|
||||||
val entries: List<BasalProgram.Segment> = basalProgram.segments
|
val entries: List<BasalProgram.Segment> = basalProgram.segments
|
||||||
assertEquals(3, entries.size)
|
assertEquals(3, entries.size)
|
||||||
|
@ -69,8 +71,11 @@ class FunctionsTest {
|
||||||
val value = Mockito.mock(ProfileValue::class.java)
|
val value = Mockito.mock(ProfileValue::class.java)
|
||||||
value.timeAsSeconds = 1800
|
value.timeAsSeconds = 1800
|
||||||
value.value = 0.5
|
value.value = 0.5
|
||||||
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOf(
|
PowerMockito.`when`(profile.basalValues).thenReturn(
|
||||||
value))
|
arrayOf(
|
||||||
|
value
|
||||||
|
)
|
||||||
|
)
|
||||||
mapProfileToBasalProgram(profile)
|
mapProfileToBasalProgram(profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,10 +90,12 @@ class FunctionsTest {
|
||||||
val value2 = Mockito.mock(ProfileValue::class.java)
|
val value2 = Mockito.mock(ProfileValue::class.java)
|
||||||
value2.timeAsSeconds = 86400
|
value2.timeAsSeconds = 86400
|
||||||
value2.value = 0.5
|
value2.value = 0.5
|
||||||
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOf(
|
PowerMockito.`when`(profile.basalValues).thenReturn(
|
||||||
|
arrayOf(
|
||||||
value1,
|
value1,
|
||||||
value2
|
value2
|
||||||
))
|
)
|
||||||
|
)
|
||||||
mapProfileToBasalProgram(profile)
|
mapProfileToBasalProgram(profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +106,11 @@ class FunctionsTest {
|
||||||
val value = Mockito.mock(ProfileValue::class.java)
|
val value = Mockito.mock(ProfileValue::class.java)
|
||||||
value.timeAsSeconds = -1
|
value.timeAsSeconds = -1
|
||||||
value.value = 0.5
|
value.value = 0.5
|
||||||
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOf(
|
PowerMockito.`when`(profile.basalValues).thenReturn(
|
||||||
value))
|
arrayOf(
|
||||||
|
value
|
||||||
|
)
|
||||||
|
)
|
||||||
mapProfileToBasalProgram(profile)
|
mapProfileToBasalProgram(profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,8 +119,11 @@ class FunctionsTest {
|
||||||
val value = Mockito.mock(ProfileValue::class.java)
|
val value = Mockito.mock(ProfileValue::class.java)
|
||||||
value.timeAsSeconds = 0
|
value.timeAsSeconds = 0
|
||||||
value.value = 0.04
|
value.value = 0.04
|
||||||
PowerMockito.`when`(profile.basalValues).thenReturn(arrayOf(
|
PowerMockito.`when`(profile.basalValues).thenReturn(
|
||||||
value))
|
arrayOf(
|
||||||
|
value
|
||||||
|
)
|
||||||
|
)
|
||||||
val basalProgram: BasalProgram = mapProfileToBasalProgram(profile)
|
val basalProgram: BasalProgram = mapProfileToBasalProgram(profile)
|
||||||
val basalProgramElement: BasalProgram.Segment = basalProgram.segments[0]
|
val basalProgramElement: BasalProgram.Segment = basalProgram.segments[0]
|
||||||
assertEquals(5, basalProgramElement.basalRateInHundredthUnitsPerHour)
|
assertEquals(5, basalProgramElement.basalRateInHundredthUnitsPerHour)
|
||||||
|
|
Loading…
Reference in a new issue