Improved switching between Dana pumps, code cleanup

This commit is contained in:
Milos Kozak 2020-03-28 20:55:28 +01:00
parent 7df82774a4
commit 5e50ca8793
26 changed files with 434 additions and 277 deletions

View file

@ -97,16 +97,16 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump
disposable.add(rxBus
.toObservable(EventConfigBuilderChange.class)
.observeOn(Schedulers.io())
.subscribe(event -> danaRPump.setLastConnection(0))
.subscribe(event -> danaRPump.reset())
);
disposable.add(rxBus
.toObservable(EventPreferenceChange.class)
.observeOn(Schedulers.io())
.subscribe(event -> {
if (event.isChanged(getResourceHelper(), R.string.key_danar_bt_name)) {
danaRPump.setLastConnection(0);
danaRPump.setLastSettingsRead(0);
getCommandQueue().readStatus("DeviceChanged", null); }
danaRPump.reset();
getCommandQueue().readStatus("DeviceChanged", null);
}
})
);
}

View file

@ -210,8 +210,8 @@ class DanaRFragment : DaggerFragment() {
danar_battery.text = "{fa-battery-" + pump.batteryRemaining / 25 + "}"
SetWarnColor.setColorInverse(danar_battery, pump.batteryRemaining.toDouble(), 51.0, 26.0)
danar_iob.text = resourceHelper.gs(R.string.formatinsulinunits, pump.iob)
if (pump.model != 0 || pump.protocol != 0 || pump.productCode != 0) {
danar_firmware.text = resourceHelper.gs(R.string.danar_model, pump.model, pump.protocol, pump.productCode)
if (pump.btModel != 0 || pump.protocol != 0 || pump.productCode != 0) {
danar_firmware.text = resourceHelper.gs(R.string.danar_model, pump.btModel, pump.protocol, pump.productCode)
} else {
@Suppress("SetTextI18n")
danar_firmware.text = "OLD"
@ -229,7 +229,7 @@ class DanaRFragment : DaggerFragment() {
//hide user options button if not an RS pump or old firmware
// also excludes pump with model 03 because of untested error
val isKorean = danaRKoreanPlugin.isEnabled(PluginType.PUMP)
if (isKorean || danar_firmware.text === "OLD" || pump.model == 3) {
if (isKorean || danar_firmware.text === "OLD" || pump.btModel == 3) {
danar_user_options.visibility = View.GONE
}
}

View file

@ -26,6 +26,20 @@ class DanaRPump @Inject constructor(
private val injector: HasAndroidInjector
) {
enum class ErrorState(val code: Int) {
NONE(0x00),
SUSPENDED(0x01),
DAILYMAX(0x02),
BOLUSBLOCK(0x04),
ORDERDELIVERING(0x08),
NOPRIME(0x10);
companion object {
private val map = values().associateBy(ErrorState::code)
operator fun get(value: Int) = map[value]
}
}
var lastConnection: Long = 0
var lastSettingsRead: Long = 0
@ -33,12 +47,14 @@ class DanaRPump @Inject constructor(
var serialNumber = ""
var shippingDate: Long = 0
var shippingCountry = ""
var isNewPump = true
var password = -1
var bleModel = "" // RS v3: like BPN-1.0.1
var isNewPump = true // R only , providing model info
var password = -1 // R, RSv1
var pumpTime: Long = 0
var model = 0
var btModel = 0
var protocol = 0
var productCode = 0
var errorState: ErrorState = ErrorState.NONE
var isConfigUD = false
var isExtendedBolusEnabled = false
var isEasyModeEnabled = false
@ -49,6 +65,7 @@ class DanaRPump @Inject constructor(
var dailyTotalUnits = 0.0
var dailyTotalBolusUnits = 0.0 // RS only
var dailyTotalBasalUnits = 0.0 // RS only
var decRatio = 0 // RS v3: [%] for pump IOB calculation
var maxDailyTotalUnits = 0
var bolusStep = 0.1
var basalStep = 0.1
@ -207,6 +224,7 @@ class DanaRPump @Inject constructor(
fun reset() {
aapsLogger.debug(LTag.PUMP, "DanaRPump reset")
lastConnection = 0
lastSettingsRead = 0
}
companion object {
@ -234,6 +252,8 @@ class DanaRPump @Inject constructor(
const val PROFILECHANGE = 13
const val CARBS = 14
const val PRIMECANNULA = 15
// Dana R btModel
const val DOMESTIC_MODEL = 0x01
const val EXPORT_MODEL = 0x03
}

View file

@ -19,14 +19,14 @@ class MsgCheckValue(
override fun handleMessage(bytes: ByteArray) {
danaRPump.isNewPump = true
aapsLogger.debug(LTag.PUMPCOMM, "New firmware confirmed")
danaRPump.model = intFromBuff(bytes, 0, 1)
danaRPump.btModel = intFromBuff(bytes, 0, 1)
danaRPump.protocol = intFromBuff(bytes, 1, 1)
danaRPump.productCode = intFromBuff(bytes, 2, 1)
if (danaRPump.model != DanaRPump.EXPORT_MODEL) {
if (danaRPump.btModel != DanaRPump.EXPORT_MODEL) {
danaRPlugin.disconnect("Wrong Model")
aapsLogger.debug(LTag.PUMPCOMM, "Wrong model selected")
}
aapsLogger.debug(LTag.PUMPCOMM, "Model: " + String.format("%02X ", danaRPump.model))
aapsLogger.debug(LTag.PUMPCOMM, "Model: " + String.format("%02X ", danaRPump.btModel))
aapsLogger.debug(LTag.PUMPCOMM, "Protocol: " + String.format("%02X ", danaRPump.protocol))
aapsLogger.debug(LTag.PUMPCOMM, "Product Code: " + String.format("%02X ", danaRPump.productCode))
}

View file

@ -225,8 +225,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService {
if (danaRPump.getPumpTime() == 0) {
// initial handshake was not successfull
// deinitialize pump
danaRPump.setLastConnection(0);
danaRPump.setLastSettingsRead(0);
danaRPump.reset();
rxBus.send(new EventDanaRNewStatus());
rxBus.send(new EventInitializationChanged());
return;

View file

@ -21,14 +21,14 @@ class MsgCheckValue_k(
override fun handleMessage(bytes: ByteArray) {
danaRPump.isNewPump = true
aapsLogger.debug(LTag.PUMPCOMM, "New firmware confirmed")
danaRPump.model = intFromBuff(bytes, 0, 1)
danaRPump.btModel = intFromBuff(bytes, 0, 1)
danaRPump.protocol = intFromBuff(bytes, 1, 1)
danaRPump.productCode = intFromBuff(bytes, 2, 1)
if (danaRPump.model != DanaRPump.DOMESTIC_MODEL) {
if (danaRPump.btModel != DanaRPump.DOMESTIC_MODEL) {
danaRKoreanPlugin.disconnect("Wrong Model")
aapsLogger.debug(LTag.PUMPCOMM, "Wrong model selected")
}
aapsLogger.debug(LTag.PUMPCOMM, "Model: " + String.format("%02X ", danaRPump.model))
aapsLogger.debug(LTag.PUMPCOMM, "Model: " + String.format("%02X ", danaRPump.btModel))
aapsLogger.debug(LTag.PUMPCOMM, "Protocol: " + String.format("%02X ", danaRPump.protocol))
aapsLogger.debug(LTag.PUMPCOMM, "Product Code: " + String.format("%02X ", danaRPump.productCode))
}

View file

@ -212,8 +212,7 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService {
if (danaRPump.getPumpTime() == 0) {
// initial handshake was not successfull
// deinitialize pump
danaRPump.setLastConnection(0);
danaRPump.setLastSettingsRead(0);
danaRPump.reset();
rxBus.send(new EventDanaRNewStatus());
rxBus.send(new EventInitializationChanged());
return;

View file

@ -161,7 +161,7 @@ public class DanaRSPlugin extends PumpPluginBase implements PumpInterface, DanaR
disposable.add(rxBus
.toObservable(EventConfigBuilderChange.class)
.observeOn(Schedulers.io())
.subscribe(event -> danaRPump.setLastConnection(0))
.subscribe(event -> danaRPump.reset())
);
disposable.add(rxBus
.toObservable(EventDanaRSDeviceChange.class)
@ -197,8 +197,7 @@ public class DanaRSPlugin extends PumpPluginBase implements PumpInterface, DanaR
public void changePump() {
mDeviceAddress = sp.getString(R.string.key_danars_address, "");
mDeviceName = sp.getString(R.string.key_danars_name, "");
danaRPump.setLastConnection(0);
danaRPump.setLastSettingsRead(0);
danaRPump.reset();
getCommandQueue().readStatus("DeviceChanged", null);
}

View file

@ -101,5 +101,8 @@ class DanaRSMessageHashTable @Inject constructor(
put(DanaRS_Packet_APS_Basal_Set_Temporary_Basal(aapsLogger, 0))
put(DanaRS_Packet_APS_History_Events(aapsLogger, rxBus, resourceHelper, activePlugin, danaRSPlugin, detailedBolusInfoStorage, 0))
put(DanaRS_Packet_APS_Set_Event_History(aapsLogger, 0, 0, 0, 0))
// v3
put(DanaRS_Packet_General_Get_Shipping_Version(aapsLogger, danaRPump))
put(DanaRS_Packet_Review_Get_Pump_Dec_Ratio(aapsLogger, danaRPump))
}
}

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
@ -8,6 +7,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.utils.resources.ResourceHelper
class DanaRS_Packet_General_Get_Pump_Check(
@ -30,14 +30,14 @@ class DanaRS_Packet_General_Get_Pump_Check(
failed = false
var dataIndex = DATA_START
var dataSize = 1
danaRPump.model = byteArrayToInt(getBytes(data, dataIndex, dataSize))
danaRPump.btModel = byteArrayToInt(getBytes(data, dataIndex, dataSize))
dataIndex += dataSize
dataSize = 1
danaRPump.protocol = byteArrayToInt(getBytes(data, dataIndex, dataSize))
dataIndex += dataSize
dataSize = 1
danaRPump.productCode = byteArrayToInt(getBytes(data, dataIndex, dataSize))
aapsLogger.debug(LTag.PUMPCOMM, "Model: " + String.format("%02X ", danaRPump.model))
aapsLogger.debug(LTag.PUMPCOMM, "Model: " + String.format("%02X ", danaRPump.btModel))
aapsLogger.debug(LTag.PUMPCOMM, "Protocol: " + String.format("%02X ", danaRPump.protocol))
aapsLogger.debug(LTag.PUMPCOMM, "Product Code: " + String.format("%02X ", danaRPump.productCode))
if (danaRPump.productCode < 2) {

View file

@ -0,0 +1,28 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import java.nio.charset.Charset
class DanaRS_Packet_General_Get_Shipping_Version(
private val aapsLogger: AAPSLogger,
private val danaRPump: DanaRPump
) : DanaRS_Packet() {
init {
opCode = BleEncryption.DANAR_PACKET__OPCODE_GENERAL__GET_SHIPPING_VERSION
aapsLogger.debug(LTag.PUMPCOMM, "New message")
}
override fun handleMessage(data: ByteArray) {
danaRPump.bleModel = data.copyOfRange(DATA_START, data.size).toString(Charset.forName("US-ASCII"))
failed = false
aapsLogger.debug(LTag.PUMPCOMM, "BLE Model: " + danaRPump.bleModel)
}
override fun getFriendlyName(): String {
return "GENERAL__GET_SHIPPING_VERSION"
}
}

View file

@ -1,9 +1,9 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
class DanaRS_Packet_General_Initial_Screen_Information(
private val aapsLogger: AAPSLogger,
@ -51,6 +51,14 @@ class DanaRS_Packet_General_Initial_Screen_Information(
dataIndex += dataSize
dataSize = 2
danaRPump.iob = byteArrayToInt(getBytes(data, dataIndex, dataSize)) / 100.0
if (data.size >= 18) {
//protocol 10+
dataIndex += dataSize
dataSize = 1
danaRPump.errorState = DanaRPump.ErrorState[byteArrayToInt(getBytes(data, dataIndex, dataSize))]
?: DanaRPump.ErrorState.NONE
aapsLogger.debug(LTag.PUMPCOMM, "ErrorState: " + danaRPump.errorState.name)
}
aapsLogger.debug(LTag.PUMPCOMM, "Pump suspended: " + danaRPump.pumpSuspended)
aapsLogger.debug(LTag.PUMPCOMM, "Temp basal in progress: " + danaRPump.isTempBasalInProgress)
aapsLogger.debug(LTag.PUMPCOMM, "Extended in progress: " + danaRPump.isExtendedInProgress)

View file

@ -0,0 +1,27 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump
import info.nightscout.androidaps.plugins.pump.danaRS.encryption.BleEncryption
class DanaRS_Packet_Review_Get_Pump_Dec_Ratio(
private val aapsLogger: AAPSLogger,
private val danaRPump: DanaRPump
) : DanaRS_Packet() {
init {
opCode = BleEncryption.DANAR_PACKET__OPCODE_REVIEW__GET_PUMP_DEC_RATIO
aapsLogger.debug(LTag.PUMPCOMM, "New message")
}
override fun handleMessage(data: ByteArray) {
danaRPump.decRatio = intFromBuff(data, 0, 1) * 5
failed = false
aapsLogger.debug(LTag.PUMPCOMM, "Dec ratio: ${danaRPump.decRatio}%")
}
override fun getFriendlyName(): String {
return "REVIEW__GET_PUMP_DEC_RATIO"
}
}

View file

@ -97,6 +97,10 @@ public class BleEncryption {
public static final int DANAR_PACKET__OPCODE__APS_HISTORY_EVENTS = 0xC2;
public static final int DANAR_PACKET__OPCODE__APS_SET_EVENT_HISTORY = 0xC3;
// v3 specific
public static final int DANAR_PACKET__OPCODE_REVIEW__GET_PUMP_DEC_RATIO = 0x80;
public static final int DANAR_PACKET__OPCODE_GENERAL__GET_SHIPPING_VERSION = 0x81;
// Easy Mode
public static final int DANAR_PACKET__OPCODE_OPTION__GET_EASY_MENU_OPTION = 0x74;
public static final int DANAR_PACKET__OPCODE_OPTION__SET_EASY_MENU_OPTION = 0x75;

View file

@ -162,7 +162,7 @@ class BLEComm @Inject internal constructor(
if (status == BluetoothGatt.GATT_SUCCESS) {
findCharacteristic()
}
sendPumpCheck()
sendConnect()
// 1st message sent to pump after connect
}
@ -295,7 +295,7 @@ class BLEComm @Inject internal constructor(
}
}
private fun readDataParsing(receviedData: ByteArray) {
private fun readDataParsing(receivedData: ByteArray) {
//aapsLogger.debug(LTag.PUMPBTCOMM, "readDataParsing")
var startSignatureFound = false
var packetIsValid = false
@ -305,8 +305,8 @@ class BLEComm @Inject internal constructor(
// decrypt 2nd level after successful connection
val incomingBuffer = if (v3Encryption && isConnected)
bleEncryption.decryptSecondLevelPacket(receviedData).also { encryptedDataRead = true }
else receviedData
bleEncryption.decryptSecondLevelPacket(receivedData).also { encryptedDataRead = true }
else receivedData
addToReadBuffer(incomingBuffer)
while (isProcessing) {
@ -356,196 +356,42 @@ class BLEComm @Inject internal constructor(
}
}
if (packetIsValid) {
try {
// decrypt the packet
bleEncryption.getDecryptedPacket(inputBuffer)?.let { decryptedBuffer ->
when (decryptedBuffer[0]) {
BleEncryption.DANAR_PACKET__TYPE_ENCRYPTION_RESPONSE.toByte() ->
when (decryptedBuffer[1]) {
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK.toByte() ->
if (decryptedBuffer.size == 4 && decryptedBuffer[2] == 'O'.toByte() && decryptedBuffer[3] == 'K'.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (OK)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
v3Encryption = false
// Grab pairing key from preferences if exists
val pairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_pairingkey) + danaRSPlugin.mDeviceName, "")
aapsLogger.debug(LTag.PUMPBTCOMM, "Using stored pairing key: $pairingKey")
if (pairingKey.isNotEmpty()) {
val encodedPairingKey = DanaRS_Packet.hexToBytes(pairingKey)
val bytes = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY, encodedPairingKey, null)
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + "ENCRYPTION__CHECK_PASSKEY" + " " + DanaRS_Packet.toHexString(bytes))
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
} else {
// Stored pairing key does not exists, request pairing
sendPairingRequest()
}
} else if (decryptedBuffer.size == 9 && decryptedBuffer[2] == 'O'.toByte() && decryptedBuffer[3] == 'K'.toByte()) {
// v3 2nd layer encryption
v3Encryption = true
val model = decryptedBuffer[5]
// val protocol = decryptedBuffer[7]
if (model == 0x05.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK V3 (OK)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
// Dana RS Pump
val randomPairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_randompairingkey) + danaRSPlugin.mDeviceName, "")
val pairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_pairingkey) + danaRSPlugin.mDeviceName, "")
if (randomPairingKey.isNotEmpty() && pairingKey.isNotEmpty()) {
val randomSyncKey = String.format("%02x", decryptedBuffer[decryptedBuffer.size - 1])
sp.putString(resourceHelper.gs(R.string.key_danars_v3_randomsynckey) + danaRSPlugin.mDeviceName, randomSyncKey)
val tPairingKey = Base64.decode(pairingKey, Base64.DEFAULT)
val tRandomPairingKey = Base64.decode(randomPairingKey, Base64.DEFAULT)
var tRandomSyncKey: Byte = 0
if (randomSyncKey.isNotEmpty()) {
tRandomSyncKey = randomSyncKey.toInt(16).toByte()
}
bleEncryption.setPairingKeys(tPairingKey, tRandomPairingKey, tRandomSyncKey)
sendV3PairingInformation(0)
} else {
sendV3PairingInformation(1)
}
} else if (model == 0x06.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK V3 EASY (OK)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
// Dana RS Easy
val bytes: ByteArray = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__GET_EASYMENU_CHECK, null, null)
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
} else if (decryptedBuffer.size == 6 && decryptedBuffer[2] == 'P'.toByte() && decryptedBuffer[3] == 'U'.toByte() && decryptedBuffer[4] == 'M'.toByte() && decryptedBuffer[5] == 'P'.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (PUMP)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
mSendQueue.clear()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, resourceHelper.gs(R.string.pumperror)))
NSUpload.uploadError(resourceHelper.gs(R.string.pumperror))
val n = Notification(Notification.PUMPERROR, resourceHelper.gs(R.string.pumperror), Notification.URGENT)
rxBus.send(EventNewNotification(n))
} else if (decryptedBuffer.size == 6 && decryptedBuffer[2] == 'B'.toByte() && decryptedBuffer[3] == 'U'.toByte() && decryptedBuffer[4] == 'S'.toByte() && decryptedBuffer[5] == 'Y'.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (BUSY)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
mSendQueue.clear()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, resourceHelper.gs(R.string.pumpbusy)))
} else {
// ERROR in response, wrong serial number
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (ERROR)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
mSendQueue.clear()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, resourceHelper.gs(R.string.connectionerror)))
sp.remove(resourceHelper.gs(R.string.key_danars_pairingkey) + danaRSPlugin.mDeviceName)
val n = Notification(Notification.WRONGSERIALNUMBER, resourceHelper.gs(R.string.wrongpassword), Notification.URGENT)
rxBus.send(EventNewNotification(n))
}
// decrypt the packet
bleEncryption.getDecryptedPacket(inputBuffer)?.let { decryptedBuffer ->
if (decryptedBuffer[0] == BleEncryption.DANAR_PACKET__TYPE_ENCRYPTION_RESPONSE.toByte()) {
when (decryptedBuffer[1]) {
// 1st packet exchange
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK.toByte() ->
processConnectResponse(decryptedBuffer)
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION.toByte() -> {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__TIME_INFORMATION " + /*message.getMessageName() + " " + */DanaRS_Packet.toHexString(decryptedBuffer))
if (v3Encryption) {
// decryptedBuffer[2] : 0x00 OK 0x01 Error, No pairing
if (decryptedBuffer[2] == 0x00.toByte()) {
val randomPairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_randompairingkey) + danaRSPlugin.mDeviceName, "")
val pairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_pairingkey) + danaRSPlugin.mDeviceName, "")
if (randomPairingKey.isNotEmpty() && pairingKey.isNotEmpty()) {
// expecting successful connect
isConnected = true
isConnecting = false
aapsLogger.debug(LTag.PUMPBTCOMM, "Connect !!")
} else {
context.startActivity(Intent(context, EnterPinActivity::class.java).also { it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
aapsLogger.debug(LTag.PUMPBTCOMM, "Request pairing keys !!")
}
} else {
sendV3PairingInformation(1)
}
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION.toByte() ->
processEncryptionResponse(decryptedBuffer)
} else {
val size = decryptedBuffer.size
var pass: Int = (decryptedBuffer[size - 1].toInt() and 0x000000FF shl 8) + (decryptedBuffer[size - 2].toInt() and 0x000000FF)
pass = pass xor 3463
danaRPump.rsPassword = Integer.toHexString(pass)
aapsLogger.debug(LTag.PUMPBTCOMM, "Pump user password: " + Integer.toHexString(pass))
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED))
isConnected = true
isConnecting = false
aapsLogger.debug(LTag.PUMPBTCOMM, "RS connected and status read")
}
}
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY.toByte() ->
processPasskeyCheck(decryptedBuffer)
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY.toByte() -> {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__CHECK_PASSKEY" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
if (decryptedBuffer[2] == 0x00.toByte()) {
// Paring is not requested, sending time info
sendTimeInfo()
} else {
// Pairing on pump is requested
sendPairingRequest()
}
}
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST.toByte() ->
processPairingRequest(decryptedBuffer)
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST.toByte() -> {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PASSKEY_REQUEST " + DanaRS_Packet.toHexString(decryptedBuffer))
if (decryptedBuffer[2] != 0x00.toByte()) {
disconnect("passkey request failed")
}
}
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_RETURN.toByte() ->
processPairingRequest2(decryptedBuffer)
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_RETURN.toByte() -> {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PASSKEY_RETURN " + DanaRS_Packet.toHexString(decryptedBuffer))
// Paring is successful, sending time info
rxBus.send(EventDanaRSPairingSuccess())
sendTimeInfo()
val pairingKey = byteArrayOf(decryptedBuffer[2], decryptedBuffer[3])
// store pairing key to preferences
sp.putString(resourceHelper.gs(R.string.key_danars_pairingkey) + danaRSPlugin.mDeviceName, DanaRS_Packet.bytesToHex(pairingKey))
aapsLogger.debug(LTag.PUMPBTCOMM, "Got pairing key: " + DanaRS_Packet.bytesToHex(pairingKey))
}
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__GET_PUMP_CHECK.toByte() -> {
if (decryptedBuffer[2] == 0x05.toByte()) {
// not easy mode, request time info
val bytes: ByteArray = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION, null, null)
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
} else {
// easy mode
val bytes: ByteArray = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__GET_EASYMENU_CHECK, null, null)
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
}
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__GET_EASYMENU_CHECK.toByte() -> {
isEasyMode = decryptedBuffer[2] == 0x01.toByte()
isUnitUD = decryptedBuffer[3] == 0x01.toByte()
// request time information
if (v3Encryption) {
sendV3PairingInformation(1)
} else {
val bytes: ByteArray = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION, null, null)
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
}
}
else -> {
// Retrieve message code from received buffer and last message sent
val originalCommand = processedMessage?.command ?: 0xFFFF
val receivedCommand = DanaRS_Packet.getCommand(decryptedBuffer)
val message: DanaRS_Packet? = if (originalCommand == receivedCommand) {
// it's response to last message
processedMessage
} else {
// it's not response to last message, create new instance
danaRSMessageHashTable.findMessage(receivedCommand)
}
if (message != null) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + message.friendlyName + " " + DanaRS_Packet.toHexString(decryptedBuffer))
// process received data
message.handleMessage(decryptedBuffer)
message.setReceived()
synchronized(message) {
// notify to sendMessage
message.notify()
}
} else {
aapsLogger.error("Unknown message received " + DanaRS_Packet.toHexString(decryptedBuffer))
}
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__GET_PUMP_CHECK.toByte() -> {
// not easy mode, request time info
if (decryptedBuffer[2] == 0x05.toByte()) sendTimeInfo()
// easy mode
else sendEasyMenuCheck()
}
BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__GET_EASYMENU_CHECK.toByte() ->
processEasyMenuCheck(decryptedBuffer)
}
} ?: throw IllegalStateException("Null decryptedInputBuffer")
} catch (e: Exception) {
aapsLogger.error("Unhandled exception", e)
}
} else {
// Retrieve message code from received buffer and last message sent
processMessage(decryptedBuffer)
}
} ?: throw IllegalStateException("Null decryptedInputBuffer")
startSignatureFound = false
packetIsValid = false
if (bufferLength < 6) {
@ -559,6 +405,216 @@ class BLEComm @Inject internal constructor(
}
}
// 1st packet v1 v3 message sent to pump after connect
private fun sendConnect() {
val deviceName = connectDeviceName
if (deviceName == null || deviceName == "") {
val n = Notification(Notification.DEVICENOTPAIRED, resourceHelper.gs(R.string.pairfirst), Notification.URGENT)
rxBus.send(EventNewNotification(n))
return
}
val bytes = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK, null, deviceName)
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + "ENCRYPTION__PUMP_CHECK (0x00)" + " " + DanaRS_Packet.toHexString(bytes))
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
// 1st packet response
private fun processConnectResponse(decryptedBuffer: ByteArray) {
// response OK v1
if (decryptedBuffer.size == 4 && decryptedBuffer[2] == 'O'.toByte() && decryptedBuffer[3] == 'K'.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (OK)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
v3Encryption = false
// Grab pairing key from preferences if exists
val pairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_pairingkey) + danaRSPlugin.mDeviceName, "")
aapsLogger.debug(LTag.PUMPBTCOMM, "Using stored pairing key: $pairingKey")
if (pairingKey.isNotEmpty()) {
sendPasskeyCheck(pairingKey)
} else {
// Stored pairing key does not exists, request pairing
sendPairingRequest()
}
// response OK v3
} else if (decryptedBuffer.size == 9 && decryptedBuffer[2] == 'O'.toByte() && decryptedBuffer[3] == 'K'.toByte()) {
// v3 2nd layer encryption
v3Encryption = true
val model = decryptedBuffer[5]
// val protocol = decryptedBuffer[7]
if (model == 0x05.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK V3 (OK)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
// Dana RS Pump
val randomPairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_randompairingkey) + danaRSPlugin.mDeviceName, "")
val pairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_pairingkey) + danaRSPlugin.mDeviceName, "")
if (randomPairingKey.isNotEmpty() && pairingKey.isNotEmpty()) {
val randomSyncKey = String.format("%02x", decryptedBuffer[decryptedBuffer.size - 1])
sp.putString(resourceHelper.gs(R.string.key_danars_v3_randomsynckey) + danaRSPlugin.mDeviceName, randomSyncKey)
val tPairingKey = Base64.decode(pairingKey, Base64.DEFAULT)
val tRandomPairingKey = Base64.decode(randomPairingKey, Base64.DEFAULT)
var tRandomSyncKey: Byte = 0
if (randomSyncKey.isNotEmpty()) {
tRandomSyncKey = randomSyncKey.toInt(16).toByte()
}
bleEncryption.setPairingKeys(tPairingKey, tRandomPairingKey, tRandomSyncKey)
sendV3PairingInformation(0)
} else {
sendV3PairingInformation(1)
}
} else if (model == 0x06.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK V3 EASY (OK)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
// Dana RS Easy
val bytes: ByteArray = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__GET_EASYMENU_CHECK, null, null)
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
// response PUMP : error status
} else if (decryptedBuffer.size == 6 && decryptedBuffer[2] == 'P'.toByte() && decryptedBuffer[3] == 'U'.toByte() && decryptedBuffer[4] == 'M'.toByte() && decryptedBuffer[5] == 'P'.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (PUMP)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
mSendQueue.clear()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, resourceHelper.gs(R.string.pumperror)))
NSUpload.uploadError(resourceHelper.gs(R.string.pumperror))
val n = Notification(Notification.PUMPERROR, resourceHelper.gs(R.string.pumperror), Notification.URGENT)
rxBus.send(EventNewNotification(n))
// response BUSY: error status
} else if (decryptedBuffer.size == 6 && decryptedBuffer[2] == 'B'.toByte() && decryptedBuffer[3] == 'U'.toByte() && decryptedBuffer[4] == 'S'.toByte() && decryptedBuffer[5] == 'Y'.toByte()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (BUSY)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
mSendQueue.clear()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, resourceHelper.gs(R.string.pumpbusy)))
} else {
// ERROR in response, wrong serial number
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PUMP_CHECK (ERROR)" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
mSendQueue.clear()
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED, resourceHelper.gs(R.string.connectionerror)))
sp.remove(resourceHelper.gs(R.string.key_danars_pairingkey) + danaRSPlugin.mDeviceName)
val n = Notification(Notification.WRONGSERIALNUMBER, resourceHelper.gs(R.string.wrongpassword), Notification.URGENT)
rxBus.send(EventNewNotification(n))
}
}
// 2nd packet v1 check passkey
private fun sendPasskeyCheck(pairingKey: String) {
val encodedPairingKey = DanaRS_Packet.hexToBytes(pairingKey)
val bytes = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__CHECK_PASSKEY, encodedPairingKey, null)
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + "ENCRYPTION__CHECK_PASSKEY" + " " + DanaRS_Packet.toHexString(bytes))
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
// 2nd packet v1 response
private fun processPasskeyCheck(decryptedBuffer: ByteArray) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__CHECK_PASSKEY" + " " + DanaRS_Packet.toHexString(decryptedBuffer))
// Paring is not requested, sending time info
if (decryptedBuffer[2] == 0x00.toByte()) sendTimeInfo()
// Pairing on pump is requested
else sendPairingRequest()
}
// 2nd packet v3
// 0x00 Start encryption, 0x01 Request pairing
private fun sendV3PairingInformation(requestNewPairing: Int) {
val params = byteArrayOf(requestNewPairing.toByte())
val bytes: ByteArray = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION, params, null)
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + "ENCRYPTION__TIME_INFORMATION" + " " + DanaRS_Packet.toHexString(bytes))
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
// 2nd packet response
private fun processEncryptionResponse(decryptedBuffer: ByteArray) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__TIME_INFORMATION " + /*message.getMessageName() + " " + */DanaRS_Packet.toHexString(decryptedBuffer))
if (v3Encryption) {
// decryptedBuffer[2] : 0x00 OK 0x01 Error, No pairing
if (decryptedBuffer[2] == 0x00.toByte()) {
val randomPairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_randompairingkey) + danaRSPlugin.mDeviceName, "")
val pairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_pairingkey) + danaRSPlugin.mDeviceName, "")
if (randomPairingKey.isNotEmpty() && pairingKey.isNotEmpty()) {
// expecting successful connect
isConnected = true
isConnecting = false
aapsLogger.debug(LTag.PUMPBTCOMM, "Connect !!")
} else {
context.startActivity(Intent(context, EnterPinActivity::class.java).also { it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
aapsLogger.debug(LTag.PUMPBTCOMM, "Request pairing keys !!")
}
} else {
sendV3PairingInformation(1)
}
} else {
val size = decryptedBuffer.size
var pass: Int = (decryptedBuffer[size - 1].toInt() and 0x000000FF shl 8) + (decryptedBuffer[size - 2].toInt() and 0x000000FF)
pass = pass xor 3463
danaRPump.rsPassword = Integer.toHexString(pass)
aapsLogger.debug(LTag.PUMPBTCOMM, "Pump user password: " + Integer.toHexString(pass))
rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED))
isConnected = true
isConnecting = false
aapsLogger.debug(LTag.PUMPBTCOMM, "RS connected and status read")
}
}
// 3rd packet v1 existing pairing
private fun sendTimeInfo() {
val bytes = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION, null, null)
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + "ENCRYPTION__TIME_INFORMATION" + " " + DanaRS_Packet.toHexString(bytes))
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
//2nd or 3rd packet v1 pairing doesn't exist
private fun sendPairingRequest() {
// Start activity which is waiting 20sec
// On pump pairing request is displayed and is waiting for conformation
context.startActivity(Intent(context, PairingHelperActivity::class.java).also { it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
val bytes = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST, null, null)
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + "ENCRYPTION__PASSKEY_REQUEST" + " " + DanaRS_Packet.toHexString(bytes))
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
// 3rd packet v3 : only after entering PIN codes
fun finishV3Pairing() {
val randomPairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_randompairingkey) + danaRSPlugin.mDeviceName, "")
val pairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_pairingkey) + danaRSPlugin.mDeviceName, "")
if (randomPairingKey.isNotEmpty() && pairingKey.isNotEmpty()) {
val tPairingKey = Base64.decode(pairingKey, Base64.DEFAULT)
val tRandomPairingKey = Base64.decode(randomPairingKey, Base64.DEFAULT)
val tRandomSyncKey: Byte = 0
bleEncryption.setPairingKeys(tPairingKey, tRandomPairingKey, tRandomSyncKey)
sendV3PairingInformation(0)
} else throw java.lang.IllegalStateException("This should not be reached")
}
// 2nd or 3rd packet v1 response
private fun processPairingRequest(decryptedBuffer: ByteArray) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PASSKEY_REQUEST " + DanaRS_Packet.toHexString(decryptedBuffer))
if (decryptedBuffer[2] != 0x00.toByte()) {
disconnect("passkey request failed")
}
}
// 2nd or 3rd packet v1 response
private fun processPairingRequest2(decryptedBuffer: ByteArray) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + "ENCRYPTION__PASSKEY_RETURN " + DanaRS_Packet.toHexString(decryptedBuffer))
// Paring is successful, sending time info
rxBus.send(EventDanaRSPairingSuccess())
sendTimeInfo()
val pairingKey = byteArrayOf(decryptedBuffer[2], decryptedBuffer[3])
// store pairing key to preferences
sp.putString(resourceHelper.gs(R.string.key_danars_pairingkey) + danaRSPlugin.mDeviceName, DanaRS_Packet.bytesToHex(pairingKey))
aapsLogger.debug(LTag.PUMPBTCOMM, "Got pairing key: " + DanaRS_Packet.bytesToHex(pairingKey))
}
// 3rd packet Easy menu pump
private fun sendEasyMenuCheck() {
val bytes: ByteArray = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__GET_EASYMENU_CHECK, null, null)
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
// 3rd packet Easy menu response
private fun processEasyMenuCheck(decryptedBuffer: ByteArray) {
isEasyMode = decryptedBuffer[2] == 0x01.toByte()
isUnitUD = decryptedBuffer[3] == 0x01.toByte()
// request time information
if (v3Encryption) sendV3PairingInformation(1)
else sendTimeInfo()
}
// the rest of packets
fun sendMessage(message: DanaRS_Packet?) {
processedMessage = message
if (message == null) return
@ -628,51 +684,27 @@ class BLEComm @Inject internal constructor(
}
}
fun finishV3Pairing() {
val randomPairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_randompairingkey) + danaRSPlugin.mDeviceName, "")
val pairingKey = sp.getString(resourceHelper.gs(R.string.key_danars_v3_pairingkey) + danaRSPlugin.mDeviceName, "")
if (randomPairingKey.isNotEmpty() && pairingKey.isNotEmpty()) {
val tPairingKey = Base64.decode(pairingKey, Base64.DEFAULT)
val tRandomPairingKey = Base64.decode(randomPairingKey, Base64.DEFAULT)
val tRandomSyncKey: Byte = 0
bleEncryption.setPairingKeys(tPairingKey, tRandomPairingKey, tRandomSyncKey)
sendV3PairingInformation(0)
// process common packet response
private fun processMessage(decryptedBuffer: ByteArray) {
val originalCommand = processedMessage?.command ?: 0xFFFF
val receivedCommand = DanaRS_Packet.getCommand(decryptedBuffer)
val message: DanaRS_Packet? = if (originalCommand == receivedCommand) {
// it's response to last message
processedMessage
} else {
// it's not response to last message, create new instance
danaRSMessageHashTable.findMessage(receivedCommand)
}
if (message != null) {
aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + message.friendlyName + " " + DanaRS_Packet.toHexString(decryptedBuffer))
// process received data
message.handleMessage(decryptedBuffer)
message.setReceived()
synchronized(message) {
// notify to sendMessage
message.notify()
}
} else aapsLogger.error("Unknown message received " + DanaRS_Packet.toHexString(decryptedBuffer))
}
// 0x00 Start encryption, 0x01 Request pairing
private fun sendV3PairingInformation(requestNewPairing: Int) {
val params = byteArrayOf(requestNewPairing.toByte())
val bytes: ByteArray = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION, params, null)
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + "ENCRYPTION__TIME_INFORMATION" + " " + DanaRS_Packet.toHexString(bytes))
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
private fun sendPairingRequest() {
// Start activity which is waiting 20sec
// On pump pairing request is displayed and is waiting for conformation
context.startActivity(Intent(context, PairingHelperActivity::class.java).also { it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) })
val bytes = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PASSKEY_REQUEST, null, null)
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + "ENCRYPTION__PASSKEY_REQUEST" + " " + DanaRS_Packet.toHexString(bytes))
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
private fun sendPumpCheck() {
// 1st message sent to pump after connect
val deviceName = connectDeviceName
if (deviceName == null || deviceName == "") {
val n = Notification(Notification.DEVICENOTPAIRED, resourceHelper.gs(R.string.pairfirst), Notification.URGENT)
rxBus.send(EventNewNotification(n))
return
}
val bytes = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__PUMP_CHECK, null, deviceName)
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + "ENCRYPTION__PUMP_CHECK (0x00)" + " " + DanaRS_Packet.toHexString(bytes))
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
private fun sendTimeInfo() {
val bytes = bleEncryption.getEncryptedPacket(BleEncryption.DANAR_PACKET__OPCODE_ENCRYPTION__TIME_INFORMATION, null, null)
aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + "ENCRYPTION__TIME_INFORMATION" + " " + DanaRS_Packet.toHexString(bytes))
writeCharacteristicNoResponse(uartWriteBTGattChar, bytes)
}
}

View file

@ -189,7 +189,7 @@ public class DanaRSService extends DaggerService {
if (danaRPump.getPumpTime() == 0) {
// initial handshake was not successfull
// deinitialize pump
danaRPump.setLastConnection(0);
danaRPump.reset();
rxBus.send(new EventDanaRNewStatus());
rxBus.send(new EventInitializationChanged());
return;
@ -221,7 +221,7 @@ public class DanaRSService extends DaggerService {
context.startActivity(i);
//deinitialize pump
danaRPump.setLastConnection(0);
danaRPump.reset();
rxBus.send(new EventDanaRNewStatus());
rxBus.send(new EventInitializationChanged());
return;

View file

@ -38,11 +38,11 @@ class MsgCheckValue_v2(
override fun handleMessage(bytes: ByteArray) {
danaRPump.isNewPump = true
aapsLogger.debug(LTag.PUMPCOMM, "New firmware confirmed")
danaRPump.model = intFromBuff(bytes, 0, 1)
danaRPump.btModel = intFromBuff(bytes, 0, 1)
danaRPump.protocol = intFromBuff(bytes, 1, 1)
danaRPump.productCode = intFromBuff(bytes, 2, 1)
if (danaRPump.model != DanaRPump.EXPORT_MODEL) {
danaRPump.lastConnection = 0
if (danaRPump.btModel != DanaRPump.EXPORT_MODEL) {
danaRPump.reset()
val notification = Notification(Notification.WRONG_DRIVER, resourceHelper.gs(R.string.pumpdrivercorrected), Notification.NORMAL)
rxBus.send(EventNewNotification(notification))
danaRPlugin.disconnect("Wrong Model")
@ -59,7 +59,7 @@ class MsgCheckValue_v2(
return
}
if (danaRPump.protocol != 2) {
danaRPump.lastConnection = 0
danaRPump.reset()
val notification = Notification(Notification.WRONG_DRIVER, resourceHelper.gs(R.string.pumpdrivercorrected), Notification.NORMAL)
rxBus.send(EventNewNotification(notification))
danaRKoreanPlugin.disconnect("Wrong Model")
@ -74,7 +74,7 @@ class MsgCheckValue_v2(
commandQueue.readStatus("PumpDriverChange", null) // force new connection
return
}
aapsLogger.debug(LTag.PUMPCOMM, "Model: " + String.format("%02X ", danaRPump.model))
aapsLogger.debug(LTag.PUMPCOMM, "Model: " + String.format("%02X ", danaRPump.btModel))
aapsLogger.debug(LTag.PUMPCOMM, "Protocol: " + String.format("%02X ", danaRPump.protocol))
aapsLogger.debug(LTag.PUMPCOMM, "Product Code: " + String.format("%02X ", danaRPump.productCode))
}

View file

@ -230,8 +230,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
if (danaRPump.getPumpTime() == 0) {
// initial handshake was not successfull
// deinitialize pump
danaRPump.setLastConnection(0);
danaRPump.setLastSettingsRead(0);
danaRPump.reset();
rxBus.send(new EventDanaRNewStatus());
rxBus.send(new EventInitializationChanged());
return;
@ -250,7 +249,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService {
context.startActivity(i);
//deinitialize pump
danaRPump.setLastConnection(0);
danaRPump.reset();
rxBus.send(new EventDanaRNewStatus());
rxBus.send(new EventInitializationChanged());
return;

View file

@ -115,7 +115,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() {
objectivesPlugin = ObjectivesPlugin(injector, aapsLogger, resourceHelper, activePlugin, sp)
comboPlugin = ComboPlugin(injector, aapsLogger, rxBus, resourceHelper, profileFunction, treatmentsPlugin, sp, commandQueue, context)
danaRPlugin = DanaRPlugin(injector, aapsLogger, rxBus, context, resourceHelper, constraintChecker, treatmentsPlugin, sp, commandQueue, danaRPump)
danaRSPlugin = DanaRSPlugin(injector, aapsLogger, rxBus, context, resourceHelper, constraintChecker, profileFunction, treatmentsPlugin, sp, commandQueue, danaRPump, detailedBolusInfoStorage)
danaRSPlugin = DanaRSPlugin(injector, aapsLogger, rxBus, context, resourceHelper, constraintChecker, profileFunction, treatmentsPlugin, sp, commandQueue, danaRPump, detailedBolusInfoStorage, fabricPrivacy)
insightPlugin = LocalInsightPlugin(injector, aapsLogger, rxBus, resourceHelper, treatmentsPlugin, sp, commandQueue, profileFunction, context)
openAPSSMBPlugin = OpenAPSSMBPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, treatmentsPlugin, iobCobCalculatorPlugin, hardLimits)
openAPSAMAPlugin = OpenAPSAMAPlugin(injector, aapsLogger, rxBus, constraintChecker, resourceHelper, profileFunction, context, activePlugin, treatmentsPlugin, iobCobCalculatorPlugin, hardLimits)

View file

@ -20,6 +20,6 @@ class MsgCheckValueTest : DanaRTestBase() {
val array = ByteArray(100)
putByteToArray(array, 0, DanaRPump.EXPORT_MODEL.toByte())
packet.handleMessage(array)
Assert.assertEquals(DanaRPump.EXPORT_MODEL, danaRPump.model)
Assert.assertEquals(DanaRPump.EXPORT_MODEL, danaRPump.btModel)
}
}

View file

@ -13,7 +13,6 @@ import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage
import info.nightscout.androidaps.plugins.pump.danaRS.comm.DanaRSTestBase
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import org.junit.Assert
import org.junit.Before
import org.junit.Test
@ -66,6 +65,6 @@ class DanaRSPluginTest : DanaRSTestBase() {
Mockito.`when`(resourceHelper.gs(eq(R.string.limitingbasalratio), anyObject(), anyObject())).thenReturn("limitingbasalratio")
Mockito.`when`(resourceHelper.gs(eq(R.string.limitingpercentrate), anyObject(), anyObject())).thenReturn("limitingpercentrate")
danaRSPlugin = DanaRSPlugin(HasAndroidInjector { AndroidInjector { Unit } }, aapsLogger, rxBus, context, resourceHelper, constraintChecker, profileFunction, treatmentsPlugin, sp, commandQueue, danaRPump, detailedBolusInfoStorage)
danaRSPlugin = DanaRSPlugin(HasAndroidInjector { AndroidInjector { Unit } }, aapsLogger, rxBus, context, resourceHelper, constraintChecker, profileFunction, treatmentsPlugin, sp, commandQueue, danaRPump, detailedBolusInfoStorage, fabricPrivacy)
}
}

View file

@ -9,7 +9,6 @@ import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import org.junit.Assert
import org.junit.Before
import org.junit.Test
@ -47,7 +46,7 @@ class DanaRS_Packet_Bolus_Set_Step_Bolus_StartTest : DanaRSTestBase() {
@Before
fun mock() {
danaRSPlugin = DanaRSPlugin(HasAndroidInjector { AndroidInjector { Unit } }, aapsLogger, rxBus, context, resourceHelper, constraintChecker, profileFunction, treatmentsPlugin, sp, commandQueue, danaRPump, detailedBolusInfoStorage)
danaRSPlugin = DanaRSPlugin(HasAndroidInjector { AndroidInjector { Unit } }, aapsLogger, rxBus, context, resourceHelper, constraintChecker, profileFunction, treatmentsPlugin, sp, commandQueue, danaRPump, detailedBolusInfoStorage, fabricPrivacy)
Mockito.`when`(constraintChecker.applyBolusConstraints(anyObject())).thenReturn(Constraint(0.0))
}
}

View file

@ -0,0 +1,20 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)
class DanaRS_Packet_General_Get_Shipping_VerisonTest : DanaRSTestBase() {
@Test fun runTest() {
val packet = DanaRS_Packet_General_Get_Shipping_Version(aapsLogger, danaRPump)
// test message decoding
val ver = byteArrayOf((-78).toByte(), (-127).toByte(), (66).toByte(), (80).toByte(), (78).toByte(), (45).toByte(), (51).toByte(), (46).toByte(), (48).toByte(), (46).toByte(), (48).toByte())
packet.handleMessage(ver)
Assert.assertFalse(packet.failed)
Assert.assertEquals("BPN-3.0.0", danaRPump.bleModel)
Assert.assertEquals("GENERAL__GET_SHIPPING_VERSION", packet.friendlyName)
}
}

View file

@ -11,7 +11,6 @@ import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin
import info.nightscout.androidaps.plugins.treatments.Treatment
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DefaultValueHelper
import org.junit.Assert
import org.junit.Before
@ -66,7 +65,7 @@ class DanaRS_Packet_Notify_Delivery_Rate_DisplayTest : DanaRSTestBase() {
@Before
fun mock() {
danaRSPlugin = DanaRSPlugin(HasAndroidInjector { AndroidInjector { Unit } }, aapsLogger, rxBus, context, resourceHelper, constraintChecker, profileFunction, treatmentsPlugin, sp, commandQueue, danaRPump, detailedBolusInfoStorage)
danaRSPlugin = DanaRSPlugin(HasAndroidInjector { AndroidInjector { Unit } }, aapsLogger, rxBus, context, resourceHelper, constraintChecker, profileFunction, treatmentsPlugin, sp, commandQueue, danaRPump, detailedBolusInfoStorage, fabricPrivacy)
danaRSPlugin.bolusingTreatment = Treatment(treatmentInjector)
}
}

View file

@ -0,0 +1,22 @@
package info.nightscout.androidaps.plugins.pump.danaRS.comm
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner::class)
@PrepareForTest()
class DanaRS_Packet_Review_Get_Pump_Dec_RatioTest : DanaRSTestBase() {
@Test fun runTest() {
val packet = DanaRS_Packet_Review_Get_Pump_Dec_Ratio(aapsLogger, danaRPump)
val array = ByteArray(100)
putByteToArray(array, 0, 4.toByte())
packet.handleMessage(array)
Assert.assertEquals(20, danaRPump.decRatio)
Assert.assertEquals("REVIEW__GET_PUMP_DEC_RATIO", packet.friendlyName)
}
}

View file

@ -33,6 +33,6 @@ class MsgCheckValue_v2Test : DanaRTestBase() {
val packet = MsgCheckValue_v2(aapsLogger, rxBus, resourceHelper, danaRPump, danaRPlugin, danaRKoreanPlugin, danaRv2Plugin, configBuilderPlugin, commandQueue)
// test message decoding
packet.handleMessage(createArray(34, 3.toByte()))
Assert.assertEquals(DanaRPump.EXPORT_MODEL, danaRPump.model)
Assert.assertEquals(DanaRPump.EXPORT_MODEL, danaRPump.btModel)
}
}