NotificationPacket
This commit is contained in:
parent
cafdd6cf8f
commit
af6445a3dc
15 changed files with 396 additions and 52 deletions
|
@ -26,6 +26,7 @@ import info.nightscout.interfaces.queue.CommandQueue
|
|||
import info.nightscout.interfaces.queue.CustomCommand
|
||||
import info.nightscout.interfaces.ui.UiInteraction
|
||||
import info.nightscout.interfaces.utils.TimeChangeType
|
||||
import info.nightscout.pump.medtrum.comm.enums.MedtrumPumpState
|
||||
import info.nightscout.pump.medtrum.ui.MedtrumOverviewFragment
|
||||
import info.nightscout.pump.medtrum.services.MedtrumService
|
||||
import info.nightscout.rx.AapsSchedulers
|
||||
|
@ -62,6 +63,7 @@ class MedtrumPlugin @Inject constructor(
|
|||
private val fabricPrivacy: FabricPrivacy,
|
||||
private val dateUtil: DateUtil,
|
||||
private val pumpSync: PumpSync,
|
||||
private val medtrumPump: MedtrumPump,
|
||||
private val uiInteraction: UiInteraction,
|
||||
private val profileFunction: ProfileFunction
|
||||
) : PumpPluginBase(
|
||||
|
@ -116,15 +118,15 @@ class MedtrumPlugin @Inject constructor(
|
|||
}
|
||||
|
||||
override fun isInitialized(): Boolean {
|
||||
return false
|
||||
return medtrumPump.pumpState > MedtrumPumpState.EJECTED
|
||||
}
|
||||
|
||||
override fun isSuspended(): Boolean {
|
||||
return true
|
||||
return medtrumPump.pumpState < MedtrumPumpState.ACTIVE || medtrumPump.pumpState > MedtrumPumpState.ACTIVE_ALT
|
||||
}
|
||||
|
||||
override fun isBusy(): Boolean {
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isConnected(): Boolean {
|
||||
|
|
|
@ -40,24 +40,21 @@ class MedtrumPump @Inject constructor(
|
|||
var pumpState = MedtrumPumpState.NONE // TODO save in SP
|
||||
var patchActivationState = PatchActivationState.NONE // TODO save in SP
|
||||
|
||||
// TODO set these setting on init
|
||||
// User settings (desired values, to be set on pump)
|
||||
var desiredPatchExpiration = false
|
||||
var desiredAlarmSetting = AlarmSetting.LIGHT_VIBRATE_AND_BEEP.code
|
||||
var desiredHourlyMaxInsulin: Int = 40
|
||||
var desiredDailyMaxInsulin: Int = 180
|
||||
|
||||
// User settings (actual value's as reported by pump)
|
||||
|
||||
// Alarm settings
|
||||
|
||||
// Pump status
|
||||
|
||||
var patchId = 0L
|
||||
var lastTimeReceivedFromPump = 0L // Time in seconds!
|
||||
var lastKnownSequenceNumber = 0
|
||||
var lastTimeReceivedFromPump = 0L // Time in seconds!
|
||||
var suspendTime = 0L // Time in seconds!
|
||||
var patchStartTime = 0L // Time in seconds!
|
||||
var patchAge = 0L // Time in seconds!
|
||||
|
||||
var reservoir = 0.0
|
||||
var primeProgress = 0
|
||||
|
||||
// Pump history
|
||||
var batteryVoltage_A = 0.0
|
||||
var batteryVoltage_B = 0.0
|
||||
|
||||
var alarmFlags = 0
|
||||
var alarmParameter = 0
|
||||
|
||||
// Last basal status update
|
||||
var lastBasalType = 0
|
||||
|
@ -70,6 +67,15 @@ class MedtrumPump @Inject constructor(
|
|||
var lastStopSequence = 0
|
||||
var lastStopPatchId = 0
|
||||
|
||||
|
||||
// TODO set these setting on init
|
||||
// User settings (desired values, to be set on pump)
|
||||
var desiredPatchExpiration = false
|
||||
var desiredAlarmSetting = AlarmSetting.LIGHT_VIBRATE_AND_BEEP.code
|
||||
var desiredHourlyMaxInsulin: Int = 40
|
||||
var desiredDailyMaxInsulin: Int = 180
|
||||
|
||||
|
||||
fun buildMedtrumProfileArray(nsProfile: Profile): ByteArray? {
|
||||
val list = nsProfile.getBasalValues()
|
||||
var basals = byteArrayOf()
|
||||
|
|
|
@ -3,7 +3,7 @@ package info.nightscout.pump.medtrum.comm.enums
|
|||
enum class MedtrumPumpState(val state: Byte) {
|
||||
NONE(0),
|
||||
IDLE(1),
|
||||
DELIVERING(2),
|
||||
FILL(2),
|
||||
PRIMING(3),
|
||||
PRIMED(4),
|
||||
EJECTING(5),
|
||||
|
@ -25,5 +25,10 @@ enum class MedtrumPumpState(val state: Byte) {
|
|||
BASE_FAULT(101),
|
||||
BATTERY_OUT(102),
|
||||
NO_CALIBRATION(103),
|
||||
STOPPED(128.toByte())
|
||||
STOPPED(128.toByte());
|
||||
|
||||
companion object {
|
||||
fun fromByte(state: Byte) = values().find { it.state == state }
|
||||
?: throw IllegalAccessException("")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,9 +50,9 @@ class ActivatePacket(injector: HasAndroidInjector, private val basalProfile: Byt
|
|||
* byte 5: lowSuspend // Value for auto mode, not used for AAPS
|
||||
* byte 6: predictiveLowSuspend // Value for auto mode, not used for AAPS
|
||||
* byte 7: predictiveLowSuspendRange // Value for auto mode, not used for AAPS
|
||||
* byte 8-9: hourlyMaxInsulin // Max hourly dose of insulin not used for now, divided by 0.05
|
||||
* byte 10-11: daylyMaxSet // Max daily dose of insulin not used for now, divided by 0.05
|
||||
* byte 12-13: tddToday // Current TDD (of present day) not used for now, divided by 0.05
|
||||
* byte 8-9: hourlyMaxInsulin // Max hourly dose of insulin, divided by 0.05
|
||||
* byte 10-11: daylyMaxSet // Max daily dose of insulin, divided by 0.05
|
||||
* byte 12-13: tddToday // Current TDD (of present day), divided by 0.05
|
||||
* byte 14: 1 // Always 1
|
||||
* bytes 15 - end // Basal profile > see MedtrumPump
|
||||
*/
|
||||
|
@ -82,6 +82,7 @@ class ActivatePacket(injector: HasAndroidInjector, private val basalProfile: Byt
|
|||
|
||||
medtrumPump.patchId = patchId
|
||||
medtrumPump.lastTimeReceivedFromPump = time
|
||||
// TODO: Handle basal here, and report to AAPS directly
|
||||
medtrumPump.handleBasalStatusUpdate(basalType, basalValue, basalSequence, basalPatchId, basalStartTime, time)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
package info.nightscout.pump.medtrum.comm.packets
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.pump.medtrum.MedtrumPump
|
||||
import info.nightscout.pump.medtrum.comm.enums.CommandType.GET_TIME
|
||||
import info.nightscout.pump.medtrum.extension.toLong
|
||||
import info.nightscout.pump.medtrum.util.MedtrumTimeUtil
|
||||
import javax.inject.Inject
|
||||
|
||||
class GetTimePacket(injector: HasAndroidInjector) : MedtrumPacket(injector) {
|
||||
|
||||
var time: Long = 0
|
||||
@Inject lateinit var medtrumPump: MedtrumPump
|
||||
|
||||
companion object {
|
||||
|
||||
|
@ -22,7 +25,8 @@ class GetTimePacket(injector: HasAndroidInjector) : MedtrumPacket(injector) {
|
|||
override fun handleResponse(data: ByteArray): Boolean {
|
||||
val success = super.handleResponse(data)
|
||||
if (success) {
|
||||
time = data.copyOfRange(RESP_TIME_START, RESP_TIME_END).toLong()
|
||||
val time = MedtrumTimeUtil().convertPumpTimeToSystemTimeSeconds(data.copyOfRange(RESP_TIME_START, RESP_TIME_END).toLong())
|
||||
medtrumPump.lastTimeReceivedFromPump = time
|
||||
}
|
||||
|
||||
return success
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
package info.nightscout.pump.medtrum.comm.packets
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.pump.medtrum.MedtrumPump
|
||||
import info.nightscout.pump.medtrum.comm.enums.MedtrumPumpState
|
||||
import info.nightscout.pump.medtrum.extension.toByteArray
|
||||
import info.nightscout.pump.medtrum.extension.toInt
|
||||
import info.nightscout.pump.medtrum.extension.toLong
|
||||
import info.nightscout.pump.medtrum.util.MedtrumTimeUtil
|
||||
import info.nightscout.rx.logging.AAPSLogger
|
||||
import info.nightscout.rx.logging.LTag
|
||||
import javax.inject.Inject
|
||||
import kotlin.experimental.and
|
||||
|
||||
class NotificationPacket(val injector: HasAndroidInjector) {
|
||||
|
||||
/**
|
||||
* This is a bit of a special packet, as it is not a command packet
|
||||
* but a notification packet. It is sent by the pump to the phone
|
||||
* when the pump has a notification to send.
|
||||
*
|
||||
* Notifications are sent regualary, regardless of the pump state.
|
||||
*
|
||||
* There can be multiple messages in one packet, this is noted by the fieldMask.
|
||||
*
|
||||
* Byte 1: State (Handle a state change directly? before analyzing further?)
|
||||
* Byte 2-3: FieldMask (BitMask which tells the fields present in the message)
|
||||
* Byte 4-end : status data
|
||||
*
|
||||
* When multiple fields are in the message, the data is concatenated.
|
||||
* This kind of message can also come as a response of SynchronizePacket,
|
||||
* and can be handled here by handleMaskedMessage() as well.
|
||||
*/
|
||||
|
||||
@Inject lateinit var aapsLogger: AAPSLogger
|
||||
@Inject lateinit var medtrumPump: MedtrumPump
|
||||
|
||||
companion object {
|
||||
private const val NOTIF_STATE_START = 0
|
||||
private const val NOTIF_STATE_END = NOTIF_STATE_START + 1
|
||||
|
||||
private const val MASK_SUSPEND = 0x01
|
||||
private const val MASK_NORMAL_BOLUS = 0x02
|
||||
private const val MASK_EXTENDED_BOLUS = 0x04
|
||||
private const val MASK_BASAL = 0x08
|
||||
|
||||
private const val MASK_SETUP = 0x10
|
||||
private const val MASK_RESERVOIR = 0x20
|
||||
private const val MASK_LIFE_TIME = 0x40
|
||||
private const val MASK_BATTERY = 0x80
|
||||
|
||||
private const val MASK_STORAGE = 0x100
|
||||
private const val MASK_ALARM = 0x200
|
||||
private const val MASK_START_TIME = 0x400
|
||||
private const val MASK_UNKNOWN_1 = 0x800
|
||||
|
||||
private const val MASK_UNUSED_CGM = 0x1000
|
||||
private const val MASK_UNUSED_COMMAND_CONFIRM = 0x2000
|
||||
private const val MASK_UNUSED_AUTO_STATUS = 0x4000
|
||||
private const val MASK_UNUSED_LEGACY = 0x8000
|
||||
}
|
||||
|
||||
init {
|
||||
injector.androidInjector().inject(this)
|
||||
}
|
||||
|
||||
fun handleNotification(notification: ByteArray) {
|
||||
val state = MedtrumPumpState.fromByte(notification[0])
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Notification state: $state, current state: ${medtrumPump.pumpState}")
|
||||
|
||||
// TODO: Do we need to emit an event on state change?
|
||||
medtrumPump.pumpState = state
|
||||
|
||||
if (notification.size > NOTIF_STATE_END) {
|
||||
handleMaskedMessage(notification.copyOfRange(NOTIF_STATE_END, notification.size))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a message with a field mask, can be used by other packets as well
|
||||
*/
|
||||
fun handleMaskedMessage(data: ByteArray) {
|
||||
val fieldMask = data.copyOfRange(0, 2).toInt()
|
||||
var offset = 2
|
||||
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Message field mask: $fieldMask")
|
||||
|
||||
if (fieldMask and MASK_SUSPEND != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Suspend notification received")
|
||||
medtrumPump.suspendTime = data.copyOfRange(offset, offset + 4).toLong()
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Suspend time: ${medtrumPump.suspendTime}")
|
||||
offset += 4
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_NORMAL_BOLUS != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Normal bolus notification received")
|
||||
var bolusData = data.copyOfRange(offset, offset + 1).toInt()
|
||||
var bolusType = bolusData and 0x7F
|
||||
var bolusCompleted = (bolusData shr 7) and 0x01
|
||||
var bolusDelivered = data.copyOfRange(offset + 1, offset + 3).toInt() / 0.05
|
||||
// TODO Sync bolus flow:
|
||||
// If bolus is known add status
|
||||
// If bolus is not known start read bolus
|
||||
// When bolus is completed, remove bolus from medtrumPump
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Bolus type: $bolusType, bolus completed: $bolusCompleted, bolus delivered: $bolusDelivered")
|
||||
offset += 3
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_EXTENDED_BOLUS != 0) {
|
||||
aapsLogger.error(LTag.PUMPCOMM, "Extended bolus notification received, extended bolus not supported!")
|
||||
// TODO Handle error and stop pump if this happens
|
||||
offset += 3
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_BASAL != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Basal notification received")
|
||||
var basalType = data.copyOfRange(offset, offset + 1)
|
||||
var basalSequence = data.copyOfRange(offset + 1, offset + 3)
|
||||
var basalInterval = data.copyOfRange(offset + 3, offset + 7)
|
||||
var basalRateAndDelivery = data.copyOfRange(offset + 7, offset + 10).toInt()
|
||||
var basalRate = basalRateAndDelivery and 0xFFF
|
||||
var basalDelivery = (basalRateAndDelivery shr 12)
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Basal type: $basalType, basal sequence: $basalSequence, basal interval: $basalInterval, basal rate: $basalRate, basal delivery: $basalDelivery")
|
||||
// TODO Sync basal flow
|
||||
offset += 10
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_SETUP != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Setup notification received")
|
||||
medtrumPump.primeProgress = data.copyOfRange(offset, offset + 1).toInt()
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Prime progress: ${medtrumPump.primeProgress}")
|
||||
offset += 1
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_RESERVOIR != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Reservoir notification received")
|
||||
medtrumPump.reservoir = data.copyOfRange(offset, offset + 2).toInt() * 0.05
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Reservoir: ${medtrumPump.reservoir}")
|
||||
offset += 2
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_LIFE_TIME != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Life time notification received")
|
||||
// TODO Check if timezone offset needs to be added
|
||||
medtrumPump.patchAge = data.copyOfRange(offset, offset + 4).toLong()
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Patch age: ${medtrumPump.patchAge}")
|
||||
offset += 4
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_BATTERY != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Battery notification received")
|
||||
var parameter = data.copyOfRange(offset, offset + 3).toInt()
|
||||
// Precision for voltage A is a guess, voltage B is the important one, threshold: < 2.64
|
||||
medtrumPump.batteryVoltage_A = (parameter and 0xFFF) / 512.0
|
||||
medtrumPump.batteryVoltage_B = (parameter shr 12) / 512.0
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Battery voltage A: ${medtrumPump.batteryVoltage_A}, battery voltage B: ${medtrumPump.batteryVoltage_B}")
|
||||
offset += 3
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_STORAGE != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Storage notification received")
|
||||
// TODO, trigger check for new sequence?
|
||||
medtrumPump.lastKnownSequenceNumber = data.copyOfRange(offset, offset + 2).toInt()
|
||||
medtrumPump.patchId = data.copyOfRange(offset + 2, offset + 4).toLong()
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Last known sequence number: ${medtrumPump.lastKnownSequenceNumber}, patch id: ${medtrumPump.patchId}")
|
||||
offset += 4
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_ALARM != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Alarm notification received")
|
||||
// Set only flags here, Alarms will be picked up by the state change
|
||||
medtrumPump.alarmFlags = data.copyOfRange(offset, offset + 2).toInt()
|
||||
medtrumPump.alarmParameter = data.copyOfRange(offset + 2, offset + 4).toInt()
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Alarm flags: ${medtrumPump.alarmFlags}, alarm parameter: ${medtrumPump.alarmParameter}")
|
||||
offset += 4
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_START_TIME != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Start time notification received")
|
||||
medtrumPump.patchStartTime = MedtrumTimeUtil().convertPumpTimeToSystemTimeSeconds(data.copyOfRange(offset, offset + 4).toLong())
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Patch start time: ${medtrumPump.patchStartTime}")
|
||||
offset += 4
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_UNKNOWN_1 != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Unknown 1 notification received, not handled!")
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_UNUSED_CGM != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Unused CGM notification received, not handled!")
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_UNUSED_COMMAND_CONFIRM != 0) {
|
||||
// This one is a warning, as this happens we need to know about it, and maybe implement
|
||||
aapsLogger.warn(LTag.PUMPCOMM, "Unused command confirm notification received, not handled!")
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_UNUSED_AUTO_STATUS != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Unused auto status notification received, not handled!")
|
||||
}
|
||||
|
||||
if (fieldMask and MASK_UNUSED_LEGACY != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "Unused legacy notification received, not handled!")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ class ReadBolusStatePacket(injector: HasAndroidInjector) : MedtrumPacket(injecto
|
|||
override fun handleResponse(data: ByteArray): Boolean {
|
||||
val success = super.handleResponse(data)
|
||||
if (success) {
|
||||
// TODO: Handle bolus data here
|
||||
bolusData = data.copyOfRange(RESP_BOLUS_DATA_START, data.size)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package info.nightscout.pump.medtrum.comm.packets
|
||||
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.pump.medtrum.MedtrumPump
|
||||
import info.nightscout.pump.medtrum.comm.enums.CommandType.SYNCHRONIZE
|
||||
import info.nightscout.pump.medtrum.comm.enums.MedtrumPumpState
|
||||
import info.nightscout.pump.medtrum.extension.toByteArray
|
||||
import info.nightscout.pump.medtrum.extension.toInt
|
||||
import info.nightscout.rx.logging.LTag
|
||||
import javax.inject.Inject
|
||||
|
||||
class SynchronizePacket(injector: HasAndroidInjector) : MedtrumPacket(injector) {
|
||||
|
||||
var state: Int = 0
|
||||
var dataFieldsPresent: Int = 0
|
||||
var syncData: ByteArray = byteArrayOf()
|
||||
@Inject lateinit var medtrumPump: MedtrumPump
|
||||
|
||||
companion object {
|
||||
|
||||
|
@ -17,6 +20,10 @@ class SynchronizePacket(injector: HasAndroidInjector) : MedtrumPacket(injector)
|
|||
private const val RESP_FIELDS_START = 7
|
||||
private const val RESP_FIELDS_END = RESP_FIELDS_START + 2
|
||||
private const val RESP_SYNC_DATA_START = 9
|
||||
|
||||
private const val MASK_SUSPEND = 0x01
|
||||
private const val MASK_NORMAL_BOLUS = 0x02
|
||||
private const val MASK_EXTENDED_BOLUS = 0x04
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -27,9 +34,36 @@ class SynchronizePacket(injector: HasAndroidInjector) : MedtrumPacket(injector)
|
|||
override fun handleResponse(data: ByteArray): Boolean {
|
||||
val success = super.handleResponse(data)
|
||||
if (success) {
|
||||
state = data.copyOfRange(RESP_STATE_START, RESP_STATE_END).toInt()
|
||||
dataFieldsPresent = data.copyOfRange(RESP_FIELDS_START, RESP_FIELDS_END).toInt()
|
||||
syncData = data.copyOfRange(RESP_SYNC_DATA_START, data.size)
|
||||
var state = MedtrumPumpState.fromByte(data[RESP_STATE_START])
|
||||
|
||||
medtrumPump.pumpState = state
|
||||
|
||||
var fieldMask = data.copyOfRange(RESP_FIELDS_START, RESP_FIELDS_END).toInt()
|
||||
var syncData = data.copyOfRange(RESP_SYNC_DATA_START, data.size)
|
||||
var offset = 0
|
||||
|
||||
if (fieldMask != 0) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "SynchronizePacket: fieldMask: $fieldMask")
|
||||
}
|
||||
|
||||
// Remove bolus fields from fieldMask if fields are present
|
||||
// TODO: Test if this workaround is needed (hence the warning log)
|
||||
if (fieldMask and MASK_SUSPEND != 0) {
|
||||
offset += 4 // If field is present, skip 4 bytes
|
||||
}
|
||||
if (fieldMask and MASK_NORMAL_BOLUS != 0) {
|
||||
aapsLogger.warn(LTag.PUMPCOMM, "SynchronizePacket: Normal bolus present removing from fieldMask")
|
||||
fieldMask = fieldMask and MASK_NORMAL_BOLUS.inv()
|
||||
syncData = syncData.copyOfRange(0, offset) + syncData.copyOfRange(offset + 3, syncData.size)
|
||||
}
|
||||
if (fieldMask and MASK_EXTENDED_BOLUS != 0) {
|
||||
aapsLogger.warn(LTag.PUMPCOMM, "SynchronizePacket: Extended bolus present removing from fieldMask")
|
||||
fieldMask = fieldMask and MASK_EXTENDED_BOLUS.inv()
|
||||
syncData = syncData.copyOfRange(0, offset) + syncData.copyOfRange(offset + 3, syncData.size)
|
||||
}
|
||||
|
||||
// Let the notification packet handle the rest of the sync data
|
||||
NotificationPacket(injector).handleMaskedMessage(fieldMask.toByteArray(2) + syncData)
|
||||
}
|
||||
|
||||
return success
|
||||
|
|
|
@ -7,8 +7,10 @@ import info.nightscout.pump.medtrum.comm.packets.AuthorizePacket
|
|||
import info.nightscout.pump.medtrum.comm.packets.CancelBolusPacket
|
||||
import info.nightscout.pump.medtrum.comm.packets.CancelTempBasalPacket
|
||||
import info.nightscout.pump.medtrum.comm.packets.GetDeviceTypePacket
|
||||
import info.nightscout.pump.medtrum.comm.packets.GetRecordPacket
|
||||
import info.nightscout.pump.medtrum.comm.packets.GetTimePacket
|
||||
import info.nightscout.pump.medtrum.comm.packets.MedtrumPacket
|
||||
import info.nightscout.pump.medtrum.comm.packets.NotificationPacket
|
||||
import info.nightscout.pump.medtrum.comm.packets.PollPatchPacket
|
||||
import info.nightscout.pump.medtrum.comm.packets.PrimePacket
|
||||
import info.nightscout.pump.medtrum.comm.packets.ReadBolusStatePacket
|
||||
|
@ -31,8 +33,10 @@ abstract class MedtrumCommModule {
|
|||
@ContributesAndroidInjector abstract fun contributesCancelBolusPacket(): CancelBolusPacket
|
||||
@ContributesAndroidInjector abstract fun contributesCancelTempBasalPacket(): CancelTempBasalPacket
|
||||
@ContributesAndroidInjector abstract fun contributesGetDeviceTypePacket(): GetDeviceTypePacket
|
||||
@ContributesAndroidInjector abstract fun contributesGetRecordPacket(): GetRecordPacket
|
||||
@ContributesAndroidInjector abstract fun contributesGetTimePacket(): GetTimePacket
|
||||
@ContributesAndroidInjector abstract fun contributesMedtrumPacket(): MedtrumPacket
|
||||
@ContributesAndroidInjector abstract fun contributesNotificationPacket(): NotificationPacket
|
||||
@ContributesAndroidInjector abstract fun contributesPollPatchPacket(): PollPatchPacket
|
||||
@ContributesAndroidInjector abstract fun contributesPrimePacket(): PrimePacket
|
||||
@ContributesAndroidInjector abstract fun contributesReadBolusStatePacket(): ReadBolusStatePacket
|
||||
|
|
|
@ -92,6 +92,7 @@ class BLEComm @Inject internal constructor(
|
|||
|
||||
var isConnected = false // TODO: These may be removed have no function
|
||||
var isConnecting = false// TODO: These may be removed have no function
|
||||
private var retryCounter = 0
|
||||
private var uartWrite: BluetoothGattCharacteristic? = null
|
||||
private var uartRead: BluetoothGattCharacteristic? = null
|
||||
|
||||
|
@ -158,6 +159,7 @@ class BLEComm @Inject internal constructor(
|
|||
}
|
||||
mDeviceSN = deviceSN
|
||||
isConnecting = true
|
||||
retryCounter = 0
|
||||
startScan()
|
||||
return true
|
||||
}
|
||||
|
@ -374,11 +376,20 @@ class BLEComm @Inject internal constructor(
|
|||
mBluetoothGatt?.discoverServices()
|
||||
}, WRITE_DELAY_MILLIS)
|
||||
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
close()
|
||||
isConnected = false
|
||||
isConnecting = false
|
||||
mCallback?.onBLEDisconnected()
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Device was disconnected " + gatt.device.name) //Device was disconnected
|
||||
if (status == 133 && isConnecting && retryCounter < 3) {
|
||||
// Special case for status 133 when we are connecting
|
||||
// We need to close gatt and try to reconnect
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "onConnectionStateChange status 133")
|
||||
close()
|
||||
startScan()
|
||||
retryCounter++
|
||||
} else {
|
||||
close()
|
||||
isConnected = false
|
||||
isConnecting = false
|
||||
mCallback?.onBLEDisconnected()
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Device was disconnected " + gatt.device.name) //Device was disconnectedS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ import info.nightscout.interfaces.pump.PumpSync
|
|||
import info.nightscout.interfaces.queue.CommandQueue
|
||||
import info.nightscout.interfaces.ui.UiInteraction
|
||||
import info.nightscout.pump.medtrum.MedtrumPlugin
|
||||
import info.nightscout.pump.medtrum.MedtrumPump
|
||||
import info.nightscout.pump.medtrum.comm.enums.MedtrumPumpState
|
||||
import info.nightscout.pump.medtrum.comm.packets.*
|
||||
import info.nightscout.pump.medtrum.extension.toInt
|
||||
import info.nightscout.pump.medtrum.extension.toLong
|
||||
|
@ -50,6 +52,7 @@ class MedtrumService : DaggerService(), BLECommCallback {
|
|||
@Inject lateinit var commandQueue: CommandQueue
|
||||
@Inject lateinit var context: Context
|
||||
@Inject lateinit var medtrumPlugin: MedtrumPlugin
|
||||
@Inject lateinit var medtrumPump: MedtrumPump
|
||||
@Inject lateinit var activePlugin: ActivePlugin
|
||||
@Inject lateinit var constraintChecker: Constraints
|
||||
@Inject lateinit var uiInteraction: UiInteraction
|
||||
|
@ -72,6 +75,29 @@ class MedtrumService : DaggerService(), BLECommCallback {
|
|||
// TODO: Stuff like this in a settings class?
|
||||
private var mLastDeviceTime: Long = 0
|
||||
|
||||
companion object {
|
||||
|
||||
private val MASK_SUSPEND = 0x01
|
||||
private val MASK_NORMAL_BOLUS = 0x02
|
||||
private val MASK_EXTENDED_BOLUS = 0x04
|
||||
private val MASK_BASAL = 0x08
|
||||
|
||||
private val MASK_SETUP = 0x10
|
||||
private val MASK_RESERVOIR = 0x20
|
||||
private val MASK_LIFE_TIME = 0x40
|
||||
private val MASK_BATTERY = 0x80
|
||||
|
||||
private val MASK_STORAGE = 0x100
|
||||
private val MASK_ALARM = 0x200
|
||||
private val MASK_START_TIME = 0x400
|
||||
private val MASK_UNKNOWN_1 = 0x800
|
||||
|
||||
private val MASK_UNUSED_CGM = 0x1000
|
||||
private val MASK_UNUSED_COMMAND_CONFIRM = 0x2000
|
||||
private val MASK_UNUSED_AUTO_STATUS = 0x4000
|
||||
private val MASK_UNUSED_LEGACY = 0x8000
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
bleComm.setCallback(this)
|
||||
|
@ -182,7 +208,7 @@ class MedtrumService : DaggerService(), BLECommCallback {
|
|||
|
||||
override fun onNotification(notification: ByteArray) {
|
||||
aapsLogger.debug(LTag.PUMPCOMM, "<<<<< onNotification" + notification.contentToString())
|
||||
// TODO
|
||||
NotificationPacket(injector).handleNotification(notification)
|
||||
}
|
||||
|
||||
override fun onIndication(indication: ByteArray) {
|
||||
|
@ -315,15 +341,14 @@ class MedtrumService : DaggerService(), BLECommCallback {
|
|||
override fun onIndication(data: ByteArray) {
|
||||
if (mPacket?.handleResponse(data) == true) {
|
||||
// Succes!
|
||||
mLastDeviceTime = (mPacket as GetTimePacket).time
|
||||
val currTimeSec = dateUtil.nowWithoutMilliseconds() / 1000
|
||||
if (abs(timeUtil.convertPumpTimeToSystemTimeSeconds(mLastDeviceTime) - currTimeSec) <= 5) { // Allow 5 sec deviation
|
||||
if (abs(timeUtil.convertPumpTimeToSystemTimeSeconds(medtrumPump.lastTimeReceivedFromPump) - currTimeSec) <= 5) { // Allow 5 sec deviation
|
||||
toState(SynchronizeState())
|
||||
} else {
|
||||
aapsLogger.debug(
|
||||
LTag.PUMPCOMM,
|
||||
"GetTimeState.onIndication need to set time. systemTime: $currTimeSec PumpTime: $mLastDeviceTime Pump Time to system time: " + timeUtil.convertPumpTimeToSystemTimeSeconds(
|
||||
mLastDeviceTime
|
||||
"GetTimeState.onIndication need to set time. systemTime: $currTimeSec PumpTime: ${medtrumPump.lastTimeReceivedFromPump} Pump Time to system time: " + timeUtil.convertPumpTimeToSystemTimeSeconds(
|
||||
medtrumPump.lastTimeReceivedFromPump
|
||||
)
|
||||
)
|
||||
toState(SetTimeState())
|
||||
|
|
|
@ -4,6 +4,7 @@ import dagger.android.AndroidInjector
|
|||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.pump.medtrum.MedtrumTestBase
|
||||
import info.nightscout.pump.medtrum.extension.toByteArray
|
||||
import info.nightscout.pump.medtrum.util.MedtrumTimeUtil
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.Assert.*
|
||||
|
||||
|
@ -13,8 +14,9 @@ class GetTimePacketTest : MedtrumTestBase() {
|
|||
|
||||
private val packetInjector = HasAndroidInjector {
|
||||
AndroidInjector {
|
||||
if (it is MedtrumPacket) {
|
||||
if (it is GetTimePacket) {
|
||||
it.aapsLogger = aapsLogger
|
||||
it.medtrumPump = medtrumPump
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +48,7 @@ class GetTimePacketTest : MedtrumTestBase() {
|
|||
// Expected values
|
||||
assertEquals(true, result)
|
||||
assertEquals(false, packet.failed)
|
||||
assertEquals(time, packet.time)
|
||||
assertEquals(MedtrumTimeUtil().convertPumpTimeToSystemTimeSeconds(time), medtrumPump.lastTimeReceivedFromPump)
|
||||
}
|
||||
|
||||
@Test fun handleResponseGivenResponseWhenMessageTooShortThenResultFalse() {
|
||||
|
@ -63,6 +65,6 @@ class GetTimePacketTest : MedtrumTestBase() {
|
|||
// Expected values
|
||||
assertEquals(false, result)
|
||||
assertEquals(true, packet.failed)
|
||||
assertEquals(0, packet.time)
|
||||
assertEquals(0, medtrumPump.lastTimeReceivedFromPump)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import org.junit.Assert.*
|
|||
|
||||
class MedtrumPacketTest : MedtrumTestBase() {
|
||||
|
||||
/** Test base behavoir of the medtrum packet, thse */
|
||||
/** Test base behavoir of the medtrum packet */
|
||||
|
||||
private val packetInjector = HasAndroidInjector {
|
||||
AndroidInjector {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package info.nightscout.pump.medtrum.comm.packets
|
||||
|
||||
import dagger.android.AndroidInjector
|
||||
import dagger.android.HasAndroidInjector
|
||||
import info.nightscout.pump.medtrum.MedtrumTestBase
|
||||
import info.nightscout.pump.medtrum.comm.enums.MedtrumPumpState
|
||||
import info.nightscout.pump.medtrum.extension.toByteArray
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.Assert.*
|
||||
|
||||
class NotificationPacketTest : MedtrumTestBase() {
|
||||
|
||||
/** Test base behavoir of the Notification packet */
|
||||
|
||||
private val packetInjector = HasAndroidInjector {
|
||||
AndroidInjector {
|
||||
if (it is NotificationPacket) {
|
||||
it.aapsLogger = aapsLogger
|
||||
it.medtrumPump = medtrumPump
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun handleNotificationGivenStatusAndDataThenStateSaved() {
|
||||
// Inputs
|
||||
val state: Byte = 1
|
||||
|
||||
// Call
|
||||
NotificationPacket(packetInjector).handleNotification(byteArrayOf(state))
|
||||
|
||||
// Expected values
|
||||
assertEquals(medtrumPump.pumpState, MedtrumPumpState.fromByte(state))
|
||||
}
|
||||
|
||||
@Test fun handleMaskedMessageGivenMaskAndDataThenDataSaved() {
|
||||
// TODO: Implement
|
||||
assertTrue(false)
|
||||
}
|
||||
}
|
|
@ -13,8 +13,13 @@ class SynchronizePacketTest : MedtrumTestBase() {
|
|||
|
||||
private val packetInjector = HasAndroidInjector {
|
||||
AndroidInjector {
|
||||
if (it is MedtrumPacket) {
|
||||
if (it is SynchronizePacket) {
|
||||
it.aapsLogger = aapsLogger
|
||||
it.medtrumPump = medtrumPump
|
||||
}
|
||||
if (it is NotificationPacket) {
|
||||
it.aapsLogger = aapsLogger
|
||||
it.medtrumPump = medtrumPump
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,10 +41,10 @@ class SynchronizePacketTest : MedtrumTestBase() {
|
|||
// Inputs
|
||||
val opCode = 3
|
||||
val responseCode = 0
|
||||
val state = 1
|
||||
val state: Byte = 1
|
||||
val dataFieldsPresent = 4046
|
||||
val syncData = byteArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
|
||||
val response = byteArrayOf(0) + opCode.toByte() + 0.toByteArray(2) + responseCode.toByteArray(2) + state.toByteArray(1) + dataFieldsPresent.toByteArray(2) + syncData
|
||||
val syncData = byteArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42)
|
||||
val response = byteArrayOf(0) + opCode.toByte() + 0.toByteArray(2) + responseCode.toByteArray(2) + state + dataFieldsPresent.toByteArray(2) + syncData
|
||||
|
||||
// Call
|
||||
val packet = SynchronizePacket(packetInjector)
|
||||
|
@ -48,9 +53,8 @@ class SynchronizePacketTest : MedtrumTestBase() {
|
|||
// Expected values
|
||||
assertEquals(true, result)
|
||||
assertEquals(false, packet.failed)
|
||||
assertEquals(state, packet.state)
|
||||
assertEquals(dataFieldsPresent, packet.dataFieldsPresent)
|
||||
assertEquals(syncData.contentToString(), packet.syncData.contentToString())
|
||||
assertEquals(state, packet.medtrumPump.pumpState.state)
|
||||
// TODO: Maybe test cutting behavoir
|
||||
}
|
||||
|
||||
@Test fun handleResponseGivenResponseWhenMessageTooShortThenResultFalse() {
|
||||
|
|
Loading…
Reference in a new issue