From ffde47d53198f94fcc14bb5fc76874b49c785450 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 31 May 2021 18:03:57 +0200 Subject: [PATCH] fix Dana 5 BLE comm --- .../androidaps/danars/comm/DanaRS_Packet.java | 248 ------------------ .../androidaps/danars/comm/DanaRS_Packet.kt | 157 +++++++++++ .../androidaps/danars/services/BLEComm.kt | 77 +++--- .../jniLibs/arm64-v8a/libBleEncryption.so | Bin 22776 -> 22776 bytes .../jniLibs/armeabi-v7a/libBleEncryption.so | Bin 26548 -> 26548 bytes .../src/main/jniLibs/x86/libBleEncryption.so | Bin 22432 -> 22432 bytes .../main/jniLibs/x86_64/libBleEncryption.so | Bin 23056 -> 23056 bytes .../danars/comm/DanaRsMessageHashTableTest.kt | 2 +- 8 files changed, 195 insertions(+), 289 deletions(-) delete mode 100644 danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet.java create mode 100644 danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet.kt diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet.java b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet.java deleted file mode 100644 index ff99f0d891..0000000000 --- a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet.java +++ /dev/null @@ -1,248 +0,0 @@ -package info.nightscout.androidaps.danars.comm; - -import android.annotation.TargetApi; -import android.os.Build; - -import org.joda.time.DateTime; - -import java.nio.charset.StandardCharsets; - -import javax.inject.Inject; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.danars.encryption.BleEncryption; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.utils.DateUtil; - -public class DanaRS_Packet { - - @Inject AAPSLogger aapsLogger; - @Inject DateUtil dateUtil; - - protected HasAndroidInjector injector; - - private static final int TYPE_START = 0; - private static final int OPCODE_START = 1; - public static final int DATA_START = 2; - - private boolean received; - public boolean failed; - protected int type = BleEncryption.DANAR_PACKET__TYPE_RESPONSE; // most of the messages, should be changed for others - protected int opCode; - - public DanaRS_Packet(HasAndroidInjector injector) { - received = false; - failed = false; - this.injector = injector; - injector.androidInjector().inject(this); - } - - public boolean success() { - return !failed; - } - public void setReceived() { - received = true; - } - - public boolean isReceived() { - return received; - } - - public int getType() { - return type; - } - - public int getOpCode() { - return opCode; - } - - public int getCommand() { - return ((type & 0xFF) << 8) + (opCode & 0xFF); - } - - public byte[] getRequestParams() { - return null; - } - - // STATIC FUNCTIONS - - public int getCommand(byte[] data) { - int type = byteArrayToInt(getBytes(data, TYPE_START, 1)); - int opCode = byteArrayToInt(getBytes(data, OPCODE_START, 1)); - return ((type & 0xFF) << 8) + (opCode & 0xFF); - } - - public void handleMessage(byte[] data) { - } - - public void handleMessageNotReceived() { - failed = true; - } - - public String getFriendlyName() { - return "UNKNOWN_PACKET"; - } - - protected byte[] getBytes(byte[] data, int srcStart, int srcLength) { - try { - byte[] ret = new byte[srcLength]; - - System.arraycopy(data, srcStart, ret, 0, srcLength); - - return ret; - } catch (Exception e) { - aapsLogger.error(LTag.PUMPBTCOMM, "Unhandled exception", e); - } - return null; - } - - protected static int byteArrayToInt(byte[] b) { - int ret; - - switch (b.length) { - case 1: - ret = b[0] & 0x000000FF; - break; - case 2: - ret = ((b[1] & 0x000000FF) << 8) + (b[0] & 0x000000FF); - break; - case 3: - ret = ((b[2] & 0x000000FF) << 16) + ((b[1] & 0x000000FF) << 8) + (b[0] & 0x000000FF); - break; - case 4: - ret = ((b[3] & 0x000000FF) << 24) + ((b[2] & 0x000000FF) << 16) + ((b[1] & 0x000000FF) << 8) + (b[0] & 0x000000FF); - break; - default: - ret = -1; - break; - } - return ret; - } - - public static synchronized long dateTimeSecFromBuff(byte[] buff, int offset) { - return - new DateTime( - 2000 + intFromBuff(buff, offset, 1), - intFromBuff(buff, offset + 1, 1), - intFromBuff(buff, offset + 2, 1), - intFromBuff(buff, offset + 3, 1), - intFromBuff(buff, offset + 4, 1), - intFromBuff(buff, offset + 5, 1) - ).getMillis(); - } - - protected static int intFromBuff(byte[] b, int srcStart, int srcLength) { - int ret; - - switch (srcLength) { - case 1: - ret = b[DATA_START + srcStart + 0] & 0x000000FF; - break; - case 2: - ret = ((b[DATA_START + srcStart + 1] & 0x000000FF) << 8) + (b[DATA_START + srcStart + 0] & 0x000000FF); - break; - case 3: - ret = ((b[DATA_START + srcStart + 2] & 0x000000FF) << 16) + ((b[DATA_START + srcStart + 1] & 0x000000FF) << 8) + (b[DATA_START + srcStart + 0] & 0x000000FF); - break; - case 4: - ret = ((b[DATA_START + srcStart + 3] & 0x000000FF) << 24) + ((b[DATA_START + srcStart + 2] & 0x000000FF) << 16) + ((b[DATA_START + srcStart + 1] & 0x000000FF) << 8) + (b[DATA_START + srcStart + 0] & 0x000000FF); - break; - default: - ret = -1; - break; - } - return ret; - } - - protected static int intFromBuffMsbLsb(byte[] b, int srcStart, int srcLength) { - int ret; - - switch (srcLength) { - case 1: - ret = b[DATA_START + srcStart] & 0x000000FF; - break; - case 2: - ret = ((b[DATA_START + srcStart] & 0x000000FF) << 8) + (b[DATA_START + srcStart + 1] & 0x000000FF); - break; - case 3: - ret = ((b[DATA_START + srcStart] & 0x000000FF) << 16) + ((b[DATA_START + srcStart + 1] & 0x000000FF) << 8) + (b[DATA_START + srcStart + 2] & 0x000000FF); - break; - case 4: - ret = ((b[DATA_START + srcStart] & 0x000000FF) << 24) + ((b[DATA_START + srcStart + 1] & 0x000000FF) << 16) + ((b[DATA_START + srcStart + 2] & 0x000000FF) << 8) + (b[DATA_START + srcStart + 3] & 0x000000FF); - break; - default: - ret = -1; - break; - } - return ret; - } - - @TargetApi(Build.VERSION_CODES.KITKAT) - public static String stringFromBuff(byte[] buff, int offset, int length) { - byte[] strbuff = new byte[length]; - System.arraycopy(buff, offset, strbuff, 0, length); - return new String(strbuff, StandardCharsets.UTF_8); - } - - public long dateFromBuff(byte[] buff, int offset) { - return - new DateTime( - 2000 + byteArrayToInt(getBytes(buff, offset, 1)), - byteArrayToInt(getBytes(buff, offset + 1, 1)), - byteArrayToInt(getBytes(buff, offset + 2, 1)), - 0, - 0 - ).getMillis(); - } - - @TargetApi(Build.VERSION_CODES.KITKAT) - - public static String asciiStringFromBuff(byte[] buff, int offset, int length) { - byte[] strbuff = new byte[length]; - System.arraycopy(buff, offset, strbuff, 0, length); - return new String(strbuff, StandardCharsets.UTF_8); - } - - public static String toHexString(byte[] buff) { - if (buff == null) - return ""; - - StringBuilder sb = new StringBuilder(); - - int count = 0; - for (byte element : buff) { - sb.append(String.format("%02X ", element)); - if (++count % 4 == 0) sb.append(" "); - } - - return sb.toString(); - } - - final private static char[] hexArray = "0123456789ABCDEF".toCharArray(); - - public static String bytesToHex(byte[] bytes) { - char[] hexChars = new char[bytes.length * 2]; - for (int j = 0; j < bytes.length; j++) { - int v = bytes[j] & 0xFF; - hexChars[j * 2] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - - public static byte[] hexToBytes(String s) { - int len = s.length(); - byte[] data = new byte[len / 2]; - for (int i = 0; i < len; i += 2) { - data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) - + Character.digit(s.charAt(i + 1), 16)); - } - return data; - } - - public static int ByteToInt(byte b) { - return b & 0x000000FF; - } - -} diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet.kt b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet.kt new file mode 100644 index 0000000000..ba0e31ebb9 --- /dev/null +++ b/danars/src/main/java/info/nightscout/androidaps/danars/comm/DanaRS_Packet.kt @@ -0,0 +1,157 @@ +package info.nightscout.androidaps.danars.comm + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.danars.encryption.BleEncryption +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.utils.DateUtil +import org.joda.time.DateTime +import java.nio.charset.StandardCharsets +import javax.inject.Inject + +open class DanaRS_Packet(protected var injector: HasAndroidInjector) { + + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var dateUtil: DateUtil + + var isReceived = false + private set + var failed = false + var type = BleEncryption.DANAR_PACKET__TYPE_RESPONSE // most of the messages, should be changed for others + protected set + var opCode = 0 + protected set + + fun success(): Boolean = !failed + + fun setReceived() { + isReceived = true + } + + val command: Int + get() = (type and 0xFF shl 8) + (opCode and 0xFF) + + open fun getRequestParams(): ByteArray = ByteArray(0) + + fun getCommand(data: ByteArray): Int { + val type = byteArrayToInt(getBytes(data, TYPE_START, 1)) + val opCode = byteArrayToInt(getBytes(data, OPCODE_START, 1)) + return (type and 0xFF shl 8) + (opCode and 0xFF) + } + + open fun handleMessage(data: ByteArray) {} + open fun handleMessageNotReceived() { + failed = true + } + + open fun getFriendlyName(): String = "UNKNOWN_PACKET" + + protected fun getBytes(data: ByteArray, srcStart: Int, srcLength: Int): ByteArray { + val ret = ByteArray(srcLength) + System.arraycopy(data, srcStart, ret, 0, srcLength) + return ret + } + + fun dateFromBuff(buff: ByteArray, offset: Int): Long = + DateTime( + 2000 + byteArrayToInt(getBytes(buff, offset, 1)), + byteArrayToInt(getBytes(buff, offset + 1, 1)), + byteArrayToInt(getBytes(buff, offset + 2, 1)), + 0, + 0 + ).millis + + protected fun byteArrayToInt(b: ByteArray): Int = + when (b.size) { + 1 -> b[0].toInt() and 0xFF + 2 -> (b[1].toInt() and 0xFF shl 8) + (b[0].toInt() and 0xFF) + 3 -> (b[2].toInt() and 0xFF shl 16) + (b[1].toInt() and 0xFF shl 8) + (b[0].toInt() and 0xFF) + 4 -> (b[3].toInt() and 0xFF shl 24) + (b[2].toInt() and 0xFF shl 16) + (b[1].toInt() and 0xFF shl 8) + (b[0].toInt() and 0xFF) + else -> -1 + } + + @Synchronized fun dateTimeSecFromBuff(buff: ByteArray, offset: Int): Long = + DateTime( + 2000 + intFromBuff(buff, offset, 1), + intFromBuff(buff, offset + 1, 1), + intFromBuff(buff, offset + 2, 1), + intFromBuff(buff, offset + 3, 1), + intFromBuff(buff, offset + 4, 1), + intFromBuff(buff, offset + 5, 1) + ).millis + + protected fun intFromBuff(b: ByteArray, srcStart: Int, srcLength: Int): Int = + when (srcLength) { + 1 -> b[DATA_START + srcStart + 0].toInt() and 0xFF + 2 -> (b[DATA_START + srcStart + 1].toInt() and 0xFF shl 8) + (b[DATA_START + srcStart + 0].toInt() and 0xFF) + 3 -> (b[DATA_START + srcStart + 2].toInt() and 0xFF shl 16) + (b[DATA_START + srcStart + 1].toInt() and 0xFF shl 8) + (b[DATA_START + srcStart + 0].toInt() and 0xFF) + 4 -> (b[DATA_START + srcStart + 3].toInt() and 0xFF shl 24) + (b[DATA_START + srcStart + 2].toInt() and 0xFF shl 16) + (b[DATA_START + srcStart + 1].toInt() and 0xFF shl 8) + (b[DATA_START + srcStart + 0].toInt() and 0xFF) + else -> -1 + } + + protected fun intFromBuffMsbLsb(b: ByteArray, srcStart: Int, srcLength: Int): Int = + when (srcLength) { + 1 -> b[DATA_START + srcStart].toInt() and 0xFF + 2 -> (b[DATA_START + srcStart].toInt() and 0xFF shl 8) + (b[DATA_START + srcStart + 1].toInt() and 0xFF) + 3 -> (b[DATA_START + srcStart].toInt() and 0xFF shl 16) + (b[DATA_START + srcStart + 1].toInt() and 0xFF shl 8) + (b[DATA_START + srcStart + 2].toInt() and 0xFF) + 4 -> (b[DATA_START + srcStart].toInt() and 0xFF shl 24) + (b[DATA_START + srcStart + 1].toInt() and 0xFF shl 16) + (b[DATA_START + srcStart + 2].toInt() and 0xFF shl 8) + (b[DATA_START + srcStart + 3].toInt() and 0xFF) + else -> -1 + } + + fun stringFromBuff(buff: ByteArray, offset: Int, length: Int): String { + val stringBuff = ByteArray(length) + System.arraycopy(buff, offset, stringBuff, 0, length) + return String(stringBuff, StandardCharsets.UTF_8) + } + + companion object { + + private const val TYPE_START = 0 + private const val OPCODE_START = 1 + const val DATA_START = 2 + + fun asciiStringFromBuff(buff: ByteArray, offset: Int, length: Int): String { + val stringBuff = ByteArray(length) + System.arraycopy(buff, offset, stringBuff, 0, length) + return String(stringBuff, StandardCharsets.UTF_8) + } + + fun toHexString(buff: ByteArray?): String { + if (buff == null) return "null" + val sb = StringBuilder() + for ((count, element) in buff.withIndex()) { + sb.append(String.format("%02X ", element)) + if ((count + 1) % 4 == 0) sb.append(" ") + } + return sb.toString() + } + + @Suppress("SpellCheckingInspection") + private val hexArray = "0123456789ABCDEF".toCharArray() + fun bytesToHex(bytes: ByteArray): String { + val hexChars = CharArray(bytes.size * 2) + for (j in bytes.indices) { + val v: Int = bytes[j].toInt() and 0xFF + hexChars[j * 2] = hexArray[v ushr 4] + hexChars[j * 2 + 1] = hexArray[v and 0x0F] + } + return String(hexChars) + } + + fun hexToBytes(s: String): ByteArray { + val len = s.length + val data = ByteArray(len / 2) + var i = 0 + while (i < len) { + data[i / 2] = ((Character.digit(s[i], 16) shl 4) + + Character.digit(s[i + 1], 16)).toByte() + i += 2 + } + return data + } + } + + init { + @Suppress("LeakingThis") + injector.androidInjector().inject(this) + } +} \ No newline at end of file diff --git a/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt b/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt index 61c506d835..866eee6251 100644 --- a/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt +++ b/danars/src/main/java/info/nightscout/androidaps/danars/services/BLEComm.kt @@ -18,6 +18,8 @@ import info.nightscout.androidaps.danars.encryption.BleEncryption import info.nightscout.androidaps.danars.encryption.EncryptionType import info.nightscout.androidaps.danars.events.EventDanaRSPairingSuccess import info.nightscout.androidaps.events.EventPumpStatusChanged +import info.nightscout.androidaps.extensions.notify +import info.nightscout.androidaps.extensions.waitMillis import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag @@ -28,8 +30,6 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.ToastUtils -import info.nightscout.androidaps.extensions.notify -import info.nightscout.androidaps.extensions.waitMillis import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import java.util.* @@ -62,6 +62,8 @@ class BLEComm @Inject internal constructor( private const val PACKET_START_BYTE = 0xA5.toByte() private const val PACKET_END_BYTE = 0x5A.toByte() + private const val BLE5_PACKET_START_BYTE = 0xAA.toByte() + private const val BLE5_PACKET_END_BYTE = 0xEE.toByte() } private var scheduledDisconnection: ScheduledFuture<*>? = null @@ -327,12 +329,8 @@ class BLEComm @Inject internal constructor( private fun addToReadBuffer(buffer: ByteArray) { //log.debug("addToReadBuffer " + DanaRS_Packet.toHexString(buffer)); - if (buffer.isEmpty()) { - return - } - if (bufferLength == 1024) { - aapsLogger.debug(LTag.PUMPBTCOMM, "1024 XXXXXXXXXXXXXX") - } + if (buffer.isEmpty()) return + synchronized(readBuffer) { // Append incoming data to input buffer System.arraycopy(buffer, 0, readBuffer, bufferLength, buffer.size) @@ -343,7 +341,6 @@ class BLEComm @Inject internal constructor( @kotlin.ExperimentalStdlibApi private fun readDataParsing(receivedData: ByteArray) { //aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< readDataParsing " + DanaRS_Packet.toHexString(receivedData)) - var startSignatureFound = false var packetIsValid = false var isProcessing: Boolean isProcessing = true @@ -363,10 +360,11 @@ class BLEComm @Inject internal constructor( while (isProcessing) { var length = 0 synchronized(readBuffer) { - // Find packet start [A5 A5] + // Find packet start [A5 A5] or [AA AA] if (bufferLength >= 6) { for (idxStartByte in 0 until bufferLength - 2) { - if (readBuffer[idxStartByte] == PACKET_START_BYTE && readBuffer[idxStartByte + 1] == PACKET_START_BYTE) { + if (readBuffer[idxStartByte] == PACKET_START_BYTE && readBuffer[idxStartByte + 1] == PACKET_START_BYTE || + readBuffer[idxStartByte] == BLE5_PACKET_START_BYTE && readBuffer[idxStartByte + 1] == BLE5_PACKET_START_BYTE) { if (idxStartByte > 0) { // if buffer doesn't start with signature remove the leading trash aapsLogger.debug(LTag.PUMPBTCOMM, "Shifting the input buffer by $idxStartByte bytes") @@ -374,29 +372,25 @@ class BLEComm @Inject internal constructor( bufferLength -= idxStartByte if (bufferLength < 0) bufferLength = 0 } - startSignatureFound = true + // A5 A5 LEN TYPE CODE PARAMS CHECKSUM1 CHECKSUM2 5A 5A or + // AA AA LEN TYPE CODE PARAMS CHECKSUM1 CHECKSUM2 EE EE + // ^---- LEN -----^ + // total packet length 2 + 1 + readBuffer[2] + 2 + 2 + length = readBuffer[2].toInt() + // test if there is enough data loaded + if (length + 7 > bufferLength) + return + // Verify packed end [5A 5A] + if (readBuffer[length + 5] == PACKET_END_BYTE && readBuffer[length + 6] == PACKET_END_BYTE || + readBuffer[length + 5] == BLE5_PACKET_END_BYTE && readBuffer[length + 6] == BLE5_PACKET_END_BYTE) { + packetIsValid = true + } else { + aapsLogger.error(LTag.PUMPBTCOMM, "Error in input data. Resetting buffer.") + bufferLength = 0 + } break } - } - } - // A5 A5 LEN TYPE CODE PARAMS CHECKSUM1 CHECKSUM2 5A 5A - // ^---- LEN -----^ - // total packet length 2 + 1 + readBuffer[2] + 2 + 2 - if (startSignatureFound) { - length = readBuffer[2].toInt() - // test if there is enough data loaded - if (length + 7 > bufferLength) return - // Verify packed end [5A 5A] - if (readBuffer[length + 5] == PACKET_END_BYTE && readBuffer[length + 6] == PACKET_END_BYTE) { - packetIsValid = true - } else if (readBuffer[length + 5] == readBuffer[length + 6]) { - // BLE5 - packetIsValid = true - readBuffer[length + 5] = PACKET_END_BYTE - readBuffer[length + 6] = PACKET_END_BYTE - } else { - aapsLogger.error(LTag.PUMPBTCOMM, "Error in input data. Resetting buffer.") - bufferLength = 0 + break } } } @@ -414,9 +408,11 @@ class BLEComm @Inject internal constructor( bufferLength -= length + 7 // now we have encrypted packet in inputBuffer - //aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< PROCESSING: " + DanaRS_Packet.toHexString(inputBuffer)) + val decrypted = bleEncryption.getDecryptedPacket(inputBuffer) + //aapsLogger.debug(LTag.PUMPBTCOMM, "XXXXXX <<<<< PROCESSING: " + DanaRS_Packet.toHexString(inputBuffer)) + //aapsLogger.debug(LTag.PUMPBTCOMM, "XXXXXY <<<<< PROCESSING: " + DanaRS_Packet.toHexString(decrypted)) // decrypt the packet - bleEncryption.getDecryptedPacket(inputBuffer)?.let { decryptedBuffer -> + decrypted?.let { decryptedBuffer -> if (decryptedBuffer[0] == BleEncryption.DANAR_PACKET__TYPE_ENCRYPTION_RESPONSE.toByte()) { when (decryptedBuffer[1]) { // 1st packet exchange @@ -450,8 +446,9 @@ class BLEComm @Inject internal constructor( // Retrieve message code from received buffer and last message sent processMessage(decryptedBuffer) } - } ?: throw IllegalStateException("Null decryptedInputBuffer") - startSignatureFound = false + } + if (decrypted == null) + throw IllegalStateException("Null decryptedInputBuffer") packetIsValid = false if (bufferLength < 6) { // stop the loop @@ -722,8 +719,8 @@ class BLEComm @Inject internal constructor( encryptedCommandSent = true processedMessage = message val command = byteArrayOf(message.type.toByte(), message.opCode.toByte()) - val params = message.requestParams - aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + message.friendlyName + " " + DanaRS_Packet.toHexString(command) + " " + DanaRS_Packet.toHexString(params)) + val params = message.getRequestParams() + aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + message.getFriendlyName() + " " + DanaRS_Packet.toHexString(command) + " " + DanaRS_Packet.toHexString(params)) var bytes = bleEncryption.getEncryptedPacket(message.opCode, params, null) // aapsLogger.debug(LTag.PUMPBTCOMM, ">>>>> " + DanaRS_Packet.toHexString(bytes)) if (encryption != EncryptionType.ENCRYPTION_DEFAULT) @@ -783,7 +780,7 @@ class BLEComm @Inject internal constructor( //SystemClock.sleep(200); if (!message.isReceived) { - aapsLogger.warn(LTag.PUMPBTCOMM, "Reply not received " + message.friendlyName) + aapsLogger.warn(LTag.PUMPBTCOMM, "Reply not received " + message.getFriendlyName()) message.handleMessageNotReceived() } // verify encryption for v3 @@ -803,7 +800,7 @@ class BLEComm @Inject internal constructor( danaRSMessageHashTable.findMessage(receivedCommand) } if (message != null) { - aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + message.friendlyName + " " + DanaRS_Packet.toHexString(decryptedBuffer)) + aapsLogger.debug(LTag.PUMPBTCOMM, "<<<<< " + message.getFriendlyName() + " " + DanaRS_Packet.toHexString(decryptedBuffer)) // process received data message.handleMessage(decryptedBuffer) message.setReceived() diff --git a/danars/src/main/jniLibs/arm64-v8a/libBleEncryption.so b/danars/src/main/jniLibs/arm64-v8a/libBleEncryption.so index 7c0c49b7e8aa0a11be777b6cad2624200c37989d..baf90143284bf75740351f28416241fa26698748 100644 GIT binary patch delta 3775 zcmc&%eNa@_6~A}iF6^$mu!{=|xUh?BR1nz(BOi)kQHW?Of-WphRIqBRsfjVM({$_v zoJ}m9V9VwtgJzP7kxs#(7H91M)>hE8Lo?cnP1D$DgO)UCJ_e^Id22Mc=kB|YY-sy; z&dk~0J0JJld(J)gy}R;BDxak7sg#7$R+bM`k|?Q2EQ(AK;*g8iD01siB?U~f4n!K|f z|HIt`+p50dj~-do@iT6>BF{liN46vDkvYvo&O}b*0#Y)v8<}TjM&?PRBF7_J;V7N8 z-GxsxkY^!tvME541R4dVAezMUY{UfQ3}l1QNr=3ZIw2z|mb=!b-V2z!9*yZCk@VYEytv$d7Ywxg^4j^ZFw7BlGay`B9OyDnQ;B%XBPK6j#ME zSBPn4G3^|&%ojwu4mcT?YFVHR+QwT8X?C| zO!Ge={0GF6F9`nw!oPtZ2BcJ6YLprqw?4h4F}ypzND7}ex+q+ovAmfQO5VW{;>eS& zW}cyjtmVf7Nj>wDkS!u%pE%~Ko(O%_G`%W6-KfOVU>x47f}r1IhF+7&+!|w_4cAQe zH1(8m&qFcR6fm3ZY5Yv6)E#3@fMsZPt0u&O7^@Z@L#r#sIuc{m!K-GwS#(C!=WPg? z?eMnQl;(&TGZ8Z;4eq1I1+xiysXk$H-`O57A$``w3RD+;&N}d=(Oz}1e6UKR zEP2ZtzCmoycFkXXk)|YH#E3pqx+{tg=qx2=XIKRz(o{Z{A%jGdUiCmvY25%&i$jwAwq>So6 zxD|gSeKjFP@JhDdadVz;Fguy-aZzS2XlzdvAw$GANJ`IoMK2>`PE%+hA9p5M)J-?Bk_IAxhU*rVp`LhAby-Jk(D?V8A z{XA;yI4t=gs9iXd?t|?M_i7|Nyt6P*BL!ea-fXQDkQ*RB?{yl4PxCxr$TLB{XMXL9 zlz}lxfBe{r`T-X$d#gLRSvF8#Bzu!D!aI=L6n(vHq(ddE4P+115=Q-dPy`(2tCugCZV7POt-b_lSrd89hsA)iE{$2Vcq!konMb{NP zMEwwoKEF}$ee;UsXjNZZQ8&;Pgz800mjrF{Fj2;K2L19`iG=R&8}5!a;-{>GNp$r7 zKB?zEHYdK(`<6T6L-^kA+u9HxKEJ3oPP_FJ)&ZptwuBEYsnFW=SbpS5-X6TVTQD@V zm+jCb-GLM3OH9X&%2eD3d_E_g3^)0{N$JnSzbyX^)fWC6gB4Wxn&~WQX&=7(_^qkt zB4hk3WBLw9} z$1x6K#lJ8P=5zsZ4&tHrF%Dws1S?>Ed?>!j*j~g}CK-DX(R-V*Q;4R|7<&`3<{o2r z5Vc=0W`hSR-MSxMVC)R6shp)ry$Fw1W`5g&YsT)GB7UFRi)_LihNiSwG<QYC7MA9E3w-uo|KL20Z$3<{B@i z+{(v^;n8K_vN}=EON)B^eu!nD-v1tBd|K6?PuGR|G1T9~{OrcpQ96T#+ZGSil_`dC z6v@X}rl?ViMcIqeRUJ1Pd2zjW7^_gk3KabjEG6Yu-8K{_!beyBR2TMEb!wW`PyO^y zJD-8md2ByUs(f*p%&!%(_J2;3KbR)VLKauDB(hZ8IrtryQ!xy$DWf$&tDSh3vZ|fd zCiP3KIFJ^oMQwvg5yiEOSYUtk+N?=_rAA_m?dGU18+$4$cfsxI=H@Z}mjLN&LJg@2 zN7f#Z=v6qpzL_>bn%`rs5s9eihYhIh68WfD1&93}qnhR947ltsG+0C_EMToGnktN1 zpcdFr=dn&t)dh#^JW1-VtJqrrf3M3+>Md95qhc9>^!hww%s;tx^@Y~X<%*YzEpWKr tV~qJ1c)7mNpk6KUA`&Qq)_?^X0$#(^|3?S~il#QWX{`ttz7lZK{{WPaSPB3D delta 4302 zcmc&&eNa@_6~A}iF1YKiuw-#rMR!4BSVUM9#WfCB{tGFALNvOV;^wEq@oK&P4yurH`{%iM!!raoMM z-wz&}+S~Erii0EWU$5=wdMoH|&{R+g$Oz)i26BR?a0YEMC<7D^ngrsDaDXO&lGt%N zwa$cI8psSv1@V@w0=Y}zM1gjoMf7I?6F}2J1|gGxd}ch4youBj7y8o>?Ji?FdfdXu zEYhrEK5Ooq$L4;yza$Wk&tqv#TMb_=kLLn$PZ?~l)JZFtRd1(0=GNbX{#w1ARp?Xb z0PoRr>`8qtEnuhhPWR0s3_doaDymV;UDv%pO zet;(hZCC}eRYa-e1wcEX0!c<`6Ui5H?N&v=?uoNHDuhqH@Notz9t*jNvu|3IuMQm) zGb|Mm9~WiI5HtLZhc{aQciBYv;6ZI)NLe>HKsPZgT za6!oT3Hxqljkh~Cx>fP0&^{xykx+5`D#^OFzIM;fy4so@J0GmswWqGWA@r1K2Bn0Z znpnDm5Q@LgF+$sa+bn#EIClEOM<^&&+Hv`mW}m58lNx-W8E+7fwA`eEcJA+HU!pU1W&SJS!dMLaW@WwK1KFpIr~ zUSNKEC*8-~Db=XjlX&iCAElh3nauB~rZd@f$9kF)Dx4Cpqm67yYBk-7oRPc z)G1@y10oXxC4-ave61mkb_4Hi&E_2Lyo}LQ5Jma@I-AFW4 zKl2qzpJ1~y4={Ju#03*b^ZQ*b&dBjnXZVu@61|?_ix$xdLpS1&O)*hYAnNn|Dgp`q zby2yK4Q5uR_LSCy-N|IPlNukscIMcWYZ!2?#^>#6sfnBggwUhn32`@XL+6B9S7>m8%o{p+_mD&o{SiijLx5`*iwt<$iCD{$SmdWf~ zc8;#4iVbC_>szWKE@qwmI+fVP*|~Ve<;-2%pRD+OzJEj5MT;&5TEq_7;*0VF!(%FP zsVZWkect6pvKt4wQr%5e5u>5c>poBN@RboVwm)YkKBhm;Eod4y!az3$J{hkWiGgQH z-jz62hF8kyg!g<=d@Pg-lw<27c-HB!$s4jLOoce3(f;la-;(T1K@F0 z^7cp@B5BYQ1p0+0w-E36gtP@FY71oF<$gmKv#4hQ@;oPRF?F%sdAxrj?=efiP09Il z{gvTviRH|>ccEm9oG0qoE~zr|szm%_jpqaW9K7)_xf5psXF=*2>nHpz87#@S`ti96 zZrf!IJwIn{oPO3<*qfiX3Ol2Pw*3uW)NYTCK6DD;S+z+tk#ZEd9>RP;#(j}phqI1-H z@k_b0WXA(b>bLFLyQ`sYXFYjz+oP_93m3ZT>gyWnw(eMmFY(St*6*#~w&H=kMohNUEgJ6ot@X_8Ir-QDMmS#n9ux+UQ(9r&lp{IjIMMVVS z;b&W6gCRc~{#EbrGaWf(=xpmyuzBc(wvj{O8^PvS)yRRs@c!*{~BlLd@Pp4}xeRzD|8KHf%S-%sS#Aa9e=f`2 zzze|Ff!$xp@>O8lx3a9q7FaX}2kdCc3`5ylaLrbg*_#$&qKTNeavxi1o|gEm?x?u9 zDEIx%(A%&e9JTSrFMbUmJr>wEE`=TX2S6w9An%5}5(&uW_GOb?9Po=Ei@b!+b|{o< zWTlt@i#vi%qx@tT1g^Y<4DsojZh{MgOQCFa*<@2HW)(#GQgoax=GhG(d&>3qPK$xQ z99eCHmzYVA2FSyZkMbDC4sdOs%JKyzVlOxkGH+8OegHND1!#@u5sm-kw!^aAq1f7x z?3>^Q4a)5D!G^y?4OF%g>`x=I+^cvpG=NPE8JGOh(4<`vE5ub%yA;B?(*BI%@uu-t zZsYlNG*#5oIVV2$^VMr~E;IXh^>n<~qpO>mTq4N-2~9)`Tpo(9IVRD|?C|;~T(ljPxz_Ds z-s8wNK{_CA-5M@uhbwbUF0oWB?)}R7MxS7P%(|gqJP%qvkev;=RxPrI9(H&`Zjx4H z4O8>k#~X5zc9g2A)X+fLl&Tz4%n$o@Rr9TxOH?Zj+u7l&TvN

UckZ`6K)c$l@i gVEh+`kFBjPVCB_`>`=95yq+7^s15_6kE)&Y-w6OSJpcdz diff --git a/danars/src/main/jniLibs/armeabi-v7a/libBleEncryption.so b/danars/src/main/jniLibs/armeabi-v7a/libBleEncryption.so index 4778aca663f1d0bbc3674de53b4fcf25ea02f2ca..f5daf1449d693d9be3843e36ac13b3e9318e9e98 100644 GIT binary patch delta 8481 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 delta 8802 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 KX*smcNBD0kPRmpP diff --git a/danars/src/main/jniLibs/x86/libBleEncryption.so b/danars/src/main/jniLibs/x86/libBleEncryption.so index e5ef3a17a49bcbc8d0c88fe2450c6e9bc0ab3b2f..b63dd5a2344d76a4cf40b9f74dfe441de32bb97b 100644 GIT binary patch delta 6218 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 GfBZk=)KP)} diff --git a/danars/src/main/jniLibs/x86_64/libBleEncryption.so b/danars/src/main/jniLibs/x86_64/libBleEncryption.so index e4c02d8842ec29409e009d2a087df710386175a9..871e79aad523b93a3492707a7faa9d91cd22b1b5 100644 GIT binary patch delta 6673 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 delta 7078 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 hyYX+Zq_QaiYKfE=bAD^e%)vJhd4!g|d&-sy{|j