dash ble: start implementing retries

Handle NACKs for now.
This commit is contained in:
Andrei Vereha 2021-03-14 20:28:16 +01:00
parent 95d7f0737c
commit 109f66a48d
5 changed files with 51 additions and 15 deletions

View file

@ -43,6 +43,10 @@ class BleIO(
return ret
}
fun peekCommand(): ByteArray? {
return incomingPackets[CharacteristicType.CMD]?.peek()
}
/***
*
* @param characteristic where to write to(CMD or DATA)
@ -82,6 +86,8 @@ class BleIO(
* The incoming queues should be empty, so we log when they are not.
*/
fun flushIncomingQueues() {
synchronized(state) { state = IOState.IDLE }
for (char in CharacteristicType.values()) {
do {
val found = incomingPackets[char]?.poll()?.also {
@ -123,6 +129,6 @@ class BleIO(
companion object {
private const val DEFAULT_IO_TIMEOUT_MS = 60000
private const val DEFAULT_IO_TIMEOUT_MS = 2000
}
}

View file

@ -8,6 +8,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptio
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.BleIO
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.CharacteristicType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.PayloadJoiner
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.packet.BlePacket
import info.nightscout.androidaps.utils.extensions.toHex
class MessageIO(private val aapsLogger: AAPSLogger, private val bleIO: BleIO) {
@ -23,6 +24,36 @@ class MessageIO(private val aapsLogger: AAPSLogger, private val bleIO: BleIO) {
throw UnexpectedCommandException(actual)
}
fun peekForNack(index: Int, packets: List<BlePacket>) {
bleIO.peekCommand()?.let {
if (it.isEmpty()) {
throw UnexpectedCommandException(BleCommand(it))
}
when (BleCommandType.byValue(it[0])) {
BleCommandType.NACK -> {
if (it.size < 2) {
throw UnexpectedCommandException(BleCommand(it))
}
val missingIdx = it[1]
if (missingIdx > packets.size) {
throw UnexpectedCommandException(BleCommand(it))
}
bleIO.sendAndConfirmPacket(CharacteristicType.DATA, packets[missingIdx.toInt()].toByteArray())
}
BleCommandType.SUCCESS -> {
if (index != packets.size - 1) {
throw UnexpectedCommandException(BleCommand(it))
}
}
else ->
throw UnexpectedCommandException(BleCommand(it))
}
}
}
fun sendMessage(msg: MessagePacket) {
bleIO.flushIncomingQueues()
bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandRTS().data)
@ -32,14 +63,13 @@ class MessageIO(private val aapsLogger: AAPSLogger, private val bleIO: BleIO) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending message: ${payload.toHex()}")
val splitter = PayloadSplitter(payload)
val packets = splitter.splitInPackets()
for (packet in packets) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending DATA: ${packet.asByteArray().toHex()}")
bleIO.sendAndConfirmPacket(CharacteristicType.DATA, packet.asByteArray())
for ((index, packet) in packets.withIndex()) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending DATA: ${packet.toByteArray().toHex()}")
bleIO.sendAndConfirmPacket(CharacteristicType.DATA, packet.toByteArray())
peekForNack(index, packets)
}
// TODO: peek for NACKs
val expectSuccess = bleIO.receivePacket(CharacteristicType.CMD)
expectCommandType(BleCommand(expectSuccess), BleCommandSuccess())
// TODO: handle NACKS/FAILS/etc
}
// TODO: use higher timeout when receiving the first packet in a message

View file

@ -4,7 +4,7 @@ import java.nio.ByteBuffer
sealed class BlePacket {
abstract fun asByteArray(): ByteArray
abstract fun toByteArray(): ByteArray
companion object {
@ -19,7 +19,7 @@ data class FirstBlePacket(
val crc32: Long? = null
) : BlePacket() {
override fun asByteArray(): ByteArray {
override fun toByteArray(): ByteArray {
val bb = ByteBuffer
.allocate(MAX_SIZE)
.put(0) // index
@ -55,7 +55,7 @@ data class FirstBlePacket(
data class MiddleBlePacket(val index: Byte, val payload: ByteArray) : BlePacket() {
override fun asByteArray(): ByteArray {
override fun toByteArray(): ByteArray {
return byteArrayOf(index) + payload
}
@ -67,7 +67,7 @@ data class MiddleBlePacket(val index: Byte, val payload: ByteArray) : BlePacket(
data class LastBlePacket(val index: Byte, val size: Byte, val payload: ByteArray, val crc32: Long) : BlePacket() {
override fun asByteArray(): ByteArray {
override fun toByteArray(): ByteArray {
val bb = ByteBuffer
.allocate(MAX_SIZE)
.put(index)
@ -90,7 +90,7 @@ data class LastBlePacket(val index: Byte, val size: Byte, val payload: ByteArray
data class LastOptionalPlusOneBlePacket(val index: Byte, val payload: ByteArray, val size: Byte) : BlePacket() {
override fun asByteArray(): ByteArray {
override fun toByteArray(): ByteArray {
return byteArrayOf(index, size) + payload + ByteArray(MAX_SIZE - payload.size - 2)
}

View file

@ -15,9 +15,9 @@ class PayloadSplitJoinTest {
random.nextBytes(payload)
val splitter = PayloadSplitter(payload)
val packets = splitter.splitInPackets()
val joiner = PayloadJoiner(packets.get(0).asByteArray())
val joiner = PayloadJoiner(packets.get(0).toByteArray())
for (p in packets.subList(1, packets.size)) {
joiner.accumulate(p.asByteArray())
joiner.accumulate(p.toByteArray())
}
val got = joiner.finalize()
assertEquals(got.toHex(), payload.toHex())

View file

@ -16,8 +16,8 @@ class PayloadSplitterTest {
val packets = splitter.splitInPackets()
assertEquals(packets.size, 2)
assertEquals(f1, packets.get(0).asByteArray().toHex())
val p2 = packets.get(1).asByteArray()
assertEquals(f1, packets.get(0).toByteArray().toHex())
val p2 = packets.get(1).toByteArray()
assertTrue(p2.size >= 10)
assertEquals(f2.subSequence(0, 20), p2.copyOfRange(0, 10).toHex())
}