dash ble: start implementing retries
Handle NACKs for now.
This commit is contained in:
parent
95d7f0737c
commit
109f66a48d
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue