Moved sequence counter to BLEComm
This commit is contained in:
parent
3027c2ffa5
commit
c2e1017d73
4 changed files with 31 additions and 101 deletions
|
@ -3,26 +3,24 @@ package info.nightscout.pump.medtrum.comm
|
||||||
import info.nightscout.pump.medtrum.encryption.Crypt
|
import info.nightscout.pump.medtrum.encryption.Crypt
|
||||||
|
|
||||||
|
|
||||||
class WriteCommandPackets() {
|
class WriteCommandPackets(data: ByteArray, sequenceNumber: Int) {
|
||||||
|
|
||||||
private val CRC_8_TABLE: IntArray = intArrayOf(0, 155, 173, 54, 193, 90, 108, 247, 25, 130, 180, 47, 216, 67, 117, 238, 50, 169, 159, 4, 243, 104, 94, 197, 43, 176, 134, 29, 234, 113, 71, 220, 100, 255, 201, 82, 165, 62, 8, 147, 125, 230, 208, 75, 188, 39, 17, 138, 86, 205, 251, 96, 151, 12, 58, 161, 79, 212, 226, 121, 142, 21, 35, 184, 200, 83, 101, 254, 9, 146, 164, 63, 209, 74, 124, 231, 16, 139, 189, 38, 250, 97, 87, 204, 59, 160, 150, 13, 227, 120, 78, 213, 34, 185, 143, 20, 172, 55, 1, 154, 109, 246, 192, 91, 181, 46, 24, 131, 116, 239, 217, 66, 158, 5, 51, 168, 95, 196, 242, 105, 135, 28, 42, 177, 70, 221, 235, 112, 11, 144, 166, 61, 202, 81, 103, 252, 18, 137, 191, 36, 211, 72, 126, 229, 57, 162, 148, 15, 248, 99, 85, 206, 32, 187, 141, 22, 225, 122, 76, 215, 111, 244, 194, 89, 174, 53, 3, 152, 118, 237, 219, 64, 183, 44, 26, 129, 93, 198, 240, 107, 156, 7, 49, 170, 68, 223, 233, 114, 133, 30, 40, 179, 195, 88, 110, 245, 2, 153, 175, 52, 218, 65, 119, 236, 27, 128, 182, 45, 241, 106, 92, 199, 48, 171, 157, 6, 232, 115, 69, 222, 41, 178, 132, 31, 167, 60, 10, 145, 102, 253, 203, 80, 190, 37, 19, 136, 127, 228, 210, 73, 149, 14, 56, 163, 84, 207, 249, 98, 140, 23, 33, 186, 77, 214, 224, 123)
|
private val CRC_8_TABLE: IntArray = intArrayOf(0, 155, 173, 54, 193, 90, 108, 247, 25, 130, 180, 47, 216, 67, 117, 238, 50, 169, 159, 4, 243, 104, 94, 197, 43, 176, 134, 29, 234, 113, 71, 220, 100, 255, 201, 82, 165, 62, 8, 147, 125, 230, 208, 75, 188, 39, 17, 138, 86, 205, 251, 96, 151, 12, 58, 161, 79, 212, 226, 121, 142, 21, 35, 184, 200, 83, 101, 254, 9, 146, 164, 63, 209, 74, 124, 231, 16, 139, 189, 38, 250, 97, 87, 204, 59, 160, 150, 13, 227, 120, 78, 213, 34, 185, 143, 20, 172, 55, 1, 154, 109, 246, 192, 91, 181, 46, 24, 131, 116, 239, 217, 66, 158, 5, 51, 168, 95, 196, 242, 105, 135, 28, 42, 177, 70, 221, 235, 112, 11, 144, 166, 61, 202, 81, 103, 252, 18, 137, 191, 36, 211, 72, 126, 229, 57, 162, 148, 15, 248, 99, 85, 206, 32, 187, 141, 22, 225, 122, 76, 215, 111, 244, 194, 89, 174, 53, 3, 152, 118, 237, 219, 64, 183, 44, 26, 129, 93, 198, 240, 107, 156, 7, 49, 170, 68, 223, 233, 114, 133, 30, 40, 179, 195, 88, 110, 245, 2, 153, 175, 52, 218, 65, 119, 236, 27, 128, 182, 45, 241, 106, 92, 199, 48, 171, 157, 6, 232, 115, 69, 222, 41, 178, 132, 31, 167, 60, 10, 145, 102, 253, 203, 80, 190, 37, 19, 136, 127, 228, 210, 73, 149, 14, 56, 163, 84, 207, 249, 98, 140, 23, 33, 186, 77, 214, 224, 123)
|
||||||
|
|
||||||
private val packages = mutableListOf<ByteArray>()
|
private val packages = mutableListOf<ByteArray>()
|
||||||
private var index = 0
|
private var index = 0
|
||||||
private var sequenceNumber = 0
|
|
||||||
|
|
||||||
fun setData(inputData: ByteArray) {
|
init {
|
||||||
resetPackets()
|
// PackageIndex: 0 initially, if there are multiple packets, for the first packet it is set to 0 (not included in CRC calculation but sent in actual header)
|
||||||
// PackageIndex: 0 initially, if there are multiple packet, for the first packet it is set to 0 (not included in crc calc but sent in actual header)
|
|
||||||
var pkgIndex = 0
|
var pkgIndex = 0
|
||||||
var header = byteArrayOf(
|
var header = byteArrayOf(
|
||||||
(inputData.size + 4).toByte(),
|
(data.size + 4).toByte(),
|
||||||
inputData[0],
|
data[0],
|
||||||
sequenceNumber.toByte(),
|
sequenceNumber.toByte(),
|
||||||
pkgIndex.toByte()
|
pkgIndex.toByte()
|
||||||
)
|
)
|
||||||
|
|
||||||
var tmp: ByteArray = header + inputData.copyOfRange(1, inputData.size)
|
var tmp: ByteArray = header + data.copyOfRange(1, data.size)
|
||||||
var totalCommand: ByteArray = tmp + calcCrc8(tmp, tmp.size).toByte()
|
var totalCommand: ByteArray = tmp + calcCrc8(tmp, tmp.size).toByte()
|
||||||
|
|
||||||
if ((totalCommand.size - header.size) <= 15) {
|
if ((totalCommand.size - header.size) <= 15) {
|
||||||
|
@ -45,7 +43,6 @@ class WriteCommandPackets() {
|
||||||
tmp = header + remainingCommand
|
tmp = header + remainingCommand
|
||||||
packages.add(tmp + calcCrc8(tmp, tmp.size).toByte())
|
packages.add(tmp + calcCrc8(tmp, tmp.size).toByte())
|
||||||
}
|
}
|
||||||
sequenceNumber = (sequenceNumber % 255) + 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNextPacket(): ByteArray? {
|
fun getNextPacket(): ByteArray? {
|
||||||
|
@ -61,11 +58,6 @@ class WriteCommandPackets() {
|
||||||
return !(index < packages.size)
|
return !(index < packages.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetPackets() {
|
|
||||||
packages.clear()
|
|
||||||
index = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun calcCrc8(value: ByteArray, size: Int): Int {
|
private fun calcCrc8(value: ByteArray, size: Int): Int {
|
||||||
var crc8 = 0
|
var crc8 = 0
|
||||||
for (i in 0 until size) {
|
for (i in 0 until size) {
|
||||||
|
|
|
@ -96,7 +96,8 @@ class BLEComm @Inject internal constructor(
|
||||||
private var uartRead: BluetoothGattCharacteristic? = null
|
private var uartRead: BluetoothGattCharacteristic? = null
|
||||||
|
|
||||||
// Read and write buffers
|
// Read and write buffers
|
||||||
private var mWritePackets = WriteCommandPackets()
|
private var mWritePackets: WriteCommandPackets? = null
|
||||||
|
private var mWriteSequenceNumber: Int = 0
|
||||||
private var mReadPacket: ReadDataPacket? = null
|
private var mReadPacket: ReadDataPacket? = null
|
||||||
|
|
||||||
private var mDeviceSN: Long = 0
|
private var mDeviceSN: Long = 0
|
||||||
|
@ -157,9 +158,6 @@ class BLEComm @Inject internal constructor(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: THIS IS A WORKAROUND TEST
|
|
||||||
mWritePackets = WriteCommandPackets()
|
|
||||||
|
|
||||||
if (mDevice != null && mDeviceSN == deviceSN) {
|
if (mDevice != null && mDeviceSN == deviceSN) {
|
||||||
// Skip scanning and directly connect to gatt
|
// Skip scanning and directly connect to gatt
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Skipping scan and directly connecting to gatt")
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Skipping scan and directly connecting to gatt")
|
||||||
|
@ -180,6 +178,8 @@ class BLEComm @Inject internal constructor(
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun connectGatt(device: BluetoothDevice) {
|
private fun connectGatt(device: BluetoothDevice) {
|
||||||
|
// Reset sequence counter
|
||||||
|
mWriteSequenceNumber = 0
|
||||||
mBluetoothGatt =
|
mBluetoothGatt =
|
||||||
device.connectGatt(context, false, mGattCallback, BluetoothDevice.TRANSPORT_LE)
|
device.connectGatt(context, false, mGattCallback, BluetoothDevice.TRANSPORT_LE)
|
||||||
}
|
}
|
||||||
|
@ -280,10 +280,12 @@ class BLEComm @Inject internal constructor(
|
||||||
|
|
||||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||||
// Check if we need to finish our command!
|
// Check if we need to finish our command!
|
||||||
synchronized(mWritePackets) {
|
mWritePackets?.let {
|
||||||
val value: ByteArray? = mWritePackets.getNextPacket()
|
synchronized(it) {
|
||||||
if (value != null) {
|
val value: ByteArray? = mWritePackets?.getNextPacket()
|
||||||
writeCharacteristic(uartWriteBTGattChar, value)
|
if (value != null) {
|
||||||
|
writeCharacteristic(uartWriteBTGattChar, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -397,21 +399,21 @@ class BLEComm @Inject internal constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
fun sendMessage(message: ByteArray) {
|
fun sendMessage(message: ByteArray) {
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "sendMessage message = " + Arrays.toString(message))
|
aapsLogger.debug(LTag.PUMPBTCOMM, "sendMessage message = " + Arrays.toString(message))
|
||||||
if (!mWritePackets.allPacketsConsumed()) {
|
if (mWritePackets?.allPacketsConsumed() == false) {
|
||||||
aapsLogger.error(LTag.PUMPBTCOMM, "sendMessage not all packets consumed!! unable to sent message!")
|
aapsLogger.error(LTag.PUMPBTCOMM, "sendMessage not all packets consumed!! unable to sent message!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
synchronized(mWritePackets) {
|
mWritePackets = WriteCommandPackets(message, mWriteSequenceNumber)
|
||||||
mWritePackets.setData(message)
|
mWriteSequenceNumber = (mWriteSequenceNumber + 1) % 256
|
||||||
val value: ByteArray? = mWritePackets.getNextPacket()
|
val value: ByteArray? = mWritePackets?.getNextPacket()
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
writeCharacteristic(uartWriteBTGattChar, value)
|
writeCharacteristic(uartWriteBTGattChar, value)
|
||||||
} else {
|
} else {
|
||||||
aapsLogger.error(LTag.PUMPBTCOMM, "sendMessage error in writePacket!")
|
aapsLogger.error(LTag.PUMPBTCOMM, "sendMessage error in writePacket!")
|
||||||
mCallback?.onSendMessageError("error in writePacket!")
|
mCallback?.onSendMessageError("error in writePacket!")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,18 +428,6 @@ class BLEComm @Inject internal constructor(
|
||||||
return mBluetoothGatt?.getService(UUID.fromString(SERVICE_UUID))
|
return mBluetoothGatt?.getService(UUID.fromString(SERVICE_UUID))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getGattCharacteristic(uuid: UUID): BluetoothGattCharacteristic? {
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "getGattCharacteristic $uuid")
|
|
||||||
val service = getGattService()
|
|
||||||
if (mBluetoothAdapter == null || mBluetoothGatt == null || service == null) {
|
|
||||||
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
|
|
||||||
isConnecting = false
|
|
||||||
isConnected = false
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return service.getCharacteristic(uuid)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
|
|
@ -123,7 +123,7 @@
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:paddingStart="2dp"
|
android:paddingStart="2dp"
|
||||||
android:paddingEnd="2dp"
|
android:paddingEnd="2dp"
|
||||||
android:text="@string/colon"
|
android:text=":"
|
||||||
android:textSize="16sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
|
@ -9,8 +9,8 @@ class WriteCommandPacketsTest {
|
||||||
fun Given14LongCommandExpectOnePacket() {
|
fun Given14LongCommandExpectOnePacket() {
|
||||||
val input = byteArrayOf(5, 2, 0, 0, 0, 0, -21, 57, -122, -56)
|
val input = byteArrayOf(5, 2, 0, 0, 0, 0, -21, 57, -122, -56)
|
||||||
val expect = byteArrayOf(14, 5, 0, 0, 2, 0, 0, 0, 0, -21, 57, -122, -56, -93, 0)
|
val expect = byteArrayOf(14, 5, 0, 0, 2, 0, 0, 0, 0, -21, 57, -122, -56, -93, 0)
|
||||||
val cmdPackets = WriteCommandPackets()
|
val sequence = 0
|
||||||
cmdPackets.setData(input)
|
val cmdPackets = WriteCommandPackets(input, sequence)
|
||||||
val output = cmdPackets.getNextPacket()
|
val output = cmdPackets.getNextPacket()
|
||||||
|
|
||||||
assertEquals(expect.contentToString(), output.contentToString())
|
assertEquals(expect.contentToString(), output.contentToString())
|
||||||
|
@ -23,8 +23,8 @@ class WriteCommandPacketsTest {
|
||||||
val expect2 = byteArrayOf(41, 18, 0, 2, 0, -96, 2, -16, 96, 2, 104, 33, 2, -32, -31, 1, -64, 3, 2, -3)
|
val expect2 = byteArrayOf(41, 18, 0, 2, 0, -96, 2, -16, 96, 2, 104, 33, 2, -32, -31, 1, -64, 3, 2, -3)
|
||||||
val expect3 = byteArrayOf(41, 18, 0, 3, -20, 36, 2, 100, -123, 2, -125, -89)
|
val expect3 = byteArrayOf(41, 18, 0, 3, -20, 36, 2, 100, -123, 2, -125, -89)
|
||||||
|
|
||||||
val cmdPackets = WriteCommandPackets()
|
val sequence = 0
|
||||||
cmdPackets.setData(input)
|
val cmdPackets = WriteCommandPackets(input, sequence)
|
||||||
val output1 = cmdPackets.getNextPacket()
|
val output1 = cmdPackets.getNextPacket()
|
||||||
val output2 = cmdPackets.getNextPacket()
|
val output2 = cmdPackets.getNextPacket()
|
||||||
val output3 = cmdPackets.getNextPacket()
|
val output3 = cmdPackets.getNextPacket()
|
||||||
|
@ -37,56 +37,4 @@ class WriteCommandPacketsTest {
|
||||||
assertNull(output4)
|
assertNull(output4)
|
||||||
assertEquals(true, cmdPackets.allPacketsConsumed())
|
assertEquals(true, cmdPackets.allPacketsConsumed())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun Given2CommandsExpectWriteIndexInHeaderIncrease() {
|
|
||||||
val input1 = byteArrayOf(66)
|
|
||||||
val input2 = byteArrayOf(99)
|
|
||||||
|
|
||||||
val expect1 = byteArrayOf(5, 66, 0, 0, -25, 0)
|
|
||||||
val expect2 = byteArrayOf(5, 99, 1, 0, 64, 0)
|
|
||||||
|
|
||||||
val cmdPackets = WriteCommandPackets()
|
|
||||||
cmdPackets.setData(input1)
|
|
||||||
|
|
||||||
val output1 = cmdPackets.getNextPacket()
|
|
||||||
|
|
||||||
cmdPackets.setData(input2)
|
|
||||||
|
|
||||||
val output2 = cmdPackets.getNextPacket()
|
|
||||||
|
|
||||||
assertEquals(expect1.contentToString(), output1.contentToString())
|
|
||||||
assertEquals(expect2.contentToString(), output2.contentToString())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun GivenSequenceNumberOverflowExpectSequenceNumber1() {
|
|
||||||
val input1 = byteArrayOf(55)
|
|
||||||
val input2 = byteArrayOf(66)
|
|
||||||
val input3 = byteArrayOf(99)
|
|
||||||
|
|
||||||
val expect1 = byteArrayOf(5, 55, -2, 0, -19, 0)
|
|
||||||
val expect2 = byteArrayOf(5, 66, -1, 0, 86, 0)
|
|
||||||
val expect3 = byteArrayOf(5, 99, 1, 0, 64, 0)
|
|
||||||
|
|
||||||
val cmdPackets = WriteCommandPackets()
|
|
||||||
|
|
||||||
// All this stuff to set the private field ^^
|
|
||||||
val sequenceNumber = WriteCommandPackets::class.java.getDeclaredField("sequenceNumber")
|
|
||||||
sequenceNumber.isAccessible = true
|
|
||||||
sequenceNumber.setInt(cmdPackets, 254)
|
|
||||||
|
|
||||||
cmdPackets.setData(input1)
|
|
||||||
val output1 = cmdPackets.getNextPacket()
|
|
||||||
|
|
||||||
cmdPackets.setData(input2)
|
|
||||||
val output2 = cmdPackets.getNextPacket()
|
|
||||||
|
|
||||||
cmdPackets.setData(input3)
|
|
||||||
val output3 = cmdPackets.getNextPacket()
|
|
||||||
|
|
||||||
assertEquals(expect1.contentToString(), output1.contentToString())
|
|
||||||
assertEquals(expect2.contentToString(), output2.contentToString())
|
|
||||||
assertEquals(expect3.contentToString(), output3.contentToString())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue