dash/ble: support both 1 and 2 byte command
It seems that the PDM is sending 1 byte commands and the POD answers with 2 byte commands. Add logging for decrypted responses. I think `eqos` means that we are expecting an ACK for the last message. Read (and log for now) a pending message if the POD is trying to sending it back while we want to send a command.
This commit is contained in:
parent
db51b762ca
commit
c337b52aa0
5 changed files with 41 additions and 19 deletions
|
@ -14,7 +14,7 @@ class BleCommandFail : BleCommand(BleCommandType.FAIL)
|
||||||
|
|
||||||
open class BleCommand(val data: ByteArray) {
|
open class BleCommand(val data: ByteArray) {
|
||||||
|
|
||||||
constructor(type: BleCommandType) : this(byteArrayOf(type.value, 0))
|
constructor(type: BleCommandType) : this(byteArrayOf(type.value))
|
||||||
|
|
||||||
constructor(type: BleCommandType, payload: ByteArray) : this(
|
constructor(type: BleCommandType, payload: ByteArray) : this(
|
||||||
byteArrayOf(type.value) + payload
|
byteArrayOf(type.value) + payload
|
||||||
|
@ -36,4 +36,5 @@ open class BleCommand(val data: ByteArray) {
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return data.contentHashCode()
|
return data.contentHashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,7 @@ enum class BleCommandType(val value: Byte) {
|
||||||
ABORT(0x03.toByte()),
|
ABORT(0x03.toByte()),
|
||||||
SUCCESS(0x04.toByte()),
|
SUCCESS(0x04.toByte()),
|
||||||
FAIL(0x05.toByte()),
|
FAIL(0x05.toByte()),
|
||||||
HELLO(
|
HELLO(0x06.toByte());
|
||||||
0x06.toByte()
|
|
||||||
);
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ class EnDecrypt(private val aapsLogger: AAPSLogger, private val nonce: Nonce, pr
|
||||||
)
|
)
|
||||||
val decryptedPayload = ByteArray(payload.size - MAC_SIZE)
|
val decryptedPayload = ByteArray(payload.size - MAC_SIZE)
|
||||||
cipher.processPacket(payload, 0, payload.size, decryptedPayload, 0)
|
cipher.processPacket(payload, 0, payload.size, decryptedPayload, 0)
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Decrypted payload ${decryptedPayload.toHex()}")
|
||||||
return msg.copy(payload = decryptedPayload)
|
return msg.copy(payload = decryptedPayload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,17 +8,34 @@ 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.BleIO
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.CharacteristicType
|
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.io.PayloadJoiner
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.CommandType
|
||||||
import info.nightscout.androidaps.utils.extensions.toHex
|
import info.nightscout.androidaps.utils.extensions.toHex
|
||||||
|
|
||||||
class MessageIO(private val aapsLogger: AAPSLogger, private val bleIO: BleIO) {
|
class MessageIO(private val aapsLogger: AAPSLogger, private val bleIO: BleIO) {
|
||||||
|
|
||||||
fun sendMessage(msg: MessagePacket) {
|
private fun expectCommandType(actual: BleCommand, expected: BleCommand) {
|
||||||
|
if (actual.data.isEmpty()) {
|
||||||
|
throw UnexpectedCommandException(actual)
|
||||||
|
}
|
||||||
|
// first byte is the command type
|
||||||
|
if (actual.data[0] == expected.data[0]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
throw UnexpectedCommandException(actual)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendMessage(msg: MessagePacket):MessagePacket? {
|
||||||
bleIO.flushIncomingQueues()
|
bleIO.flushIncomingQueues()
|
||||||
bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandRTS().data)
|
bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandRTS().data)
|
||||||
val expectCTS = bleIO.receivePacket(CharacteristicType.CMD)
|
val expectCTS = bleIO.receivePacket(CharacteristicType.CMD)
|
||||||
if (BleCommand(expectCTS) != BleCommandCTS()) {
|
if (expectCTS.isEmpty()) {
|
||||||
throw UnexpectedCommandException(BleCommand(expectCTS))
|
throw UnexpectedCommandException(BleCommand(expectCTS))
|
||||||
}
|
}
|
||||||
|
//if (expectCTS[0] == BleCommandType.RTS.value) {
|
||||||
|
//the pod is trying to send something, after we sent RTS, let's read it
|
||||||
|
//}
|
||||||
|
expectCommandType(BleCommand(expectCTS), BleCommandCTS())
|
||||||
val payload = msg.asByteArray()
|
val payload = msg.asByteArray()
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending message: ${payload.toHex()}")
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending message: ${payload.toHex()}")
|
||||||
val splitter = PayloadSplitter(payload)
|
val splitter = PayloadSplitter(payload)
|
||||||
|
@ -29,17 +46,18 @@ class MessageIO(private val aapsLogger: AAPSLogger, private val bleIO: BleIO) {
|
||||||
}
|
}
|
||||||
// TODO: peek for NACKs
|
// TODO: peek for NACKs
|
||||||
val expectSuccess = bleIO.receivePacket(CharacteristicType.CMD)
|
val expectSuccess = bleIO.receivePacket(CharacteristicType.CMD)
|
||||||
if (BleCommand(expectSuccess) != BleCommandSuccess()) {
|
expectCommandType(BleCommand(expectSuccess), BleCommandSuccess())
|
||||||
throw UnexpectedCommandException(BleCommand(expectSuccess))
|
|
||||||
}
|
|
||||||
// TODO: handle NACKS/FAILS/etc
|
// TODO: handle NACKS/FAILS/etc
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun receiveMessage(): MessagePacket {
|
// TODO: use higher timeout when receiving the first packet in a message
|
||||||
val expectRTS = bleIO.receivePacket(CharacteristicType.CMD)
|
fun receiveMessage( firstCmd: ByteArray? = null): MessagePacket {
|
||||||
if (BleCommand(expectRTS) != BleCommandRTS()) {
|
var expectRTS = firstCmd
|
||||||
throw UnexpectedCommandException(BleCommand(expectRTS))
|
if (expectRTS == null) {
|
||||||
|
expectRTS = bleIO.receivePacket(CharacteristicType.CMD)
|
||||||
}
|
}
|
||||||
|
expectCommandType(BleCommand(expectRTS), BleCommandRTS())
|
||||||
bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandCTS().data)
|
bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandCTS().data)
|
||||||
try {
|
try {
|
||||||
val joiner = PayloadJoiner(bleIO.receivePacket(CharacteristicType.DATA))
|
val joiner = PayloadJoiner(bleIO.receivePacket(CharacteristicType.DATA))
|
||||||
|
|
|
@ -31,12 +31,14 @@ class Session(
|
||||||
*/
|
*/
|
||||||
fun sendCommand(cmd: Command): Response {
|
fun sendCommand(cmd: Command): Response {
|
||||||
sessionKeys.msgSequenceNumber++
|
sessionKeys.msgSequenceNumber++
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending command: ${cmd.encoded.toHex()}")
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending command: ${cmd.encoded.toHex()} in packet $cmd")
|
||||||
|
|
||||||
val msg = getCmdMessage(cmd)
|
val msg = getCmdMessage(cmd)
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending command(wrapped): ${msg.payload.toHex()}")
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending command(wrapped): ${msg.payload.toHex()}")
|
||||||
msgIO.sendMessage(msg)
|
val reply = msgIO.sendMessage(msg)
|
||||||
|
if (reply != null) { // TODO : this means the last ACK was not received, send it again?
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Received a message with payload instead of CTS: ${reply.payload.toHex()} in packet $reply")
|
||||||
|
}
|
||||||
val responseMsg = msgIO.receiveMessage()
|
val responseMsg = msgIO.receiveMessage()
|
||||||
val decrypted = enDecrypt.decrypt(responseMsg)
|
val decrypted = enDecrypt.decrypt(responseMsg)
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Received response: $decrypted")
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Received response: $decrypted")
|
||||||
|
@ -44,13 +46,15 @@ class Session(
|
||||||
|
|
||||||
sessionKeys.msgSequenceNumber++
|
sessionKeys.msgSequenceNumber++
|
||||||
val ack = getAck(responseMsg)
|
val ack = getAck(responseMsg)
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending ACK: ${ack.payload.toHex()}")
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending ACK: ${ack.payload.toHex()} in packet $ack")
|
||||||
msgIO.sendMessage(ack)
|
msgIO.sendMessage(ack)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseResponse(decrypted: MessagePacket): Response {
|
private fun parseResponse(decrypted: MessagePacket): Response {
|
||||||
|
|
||||||
val payload = parseKeys(arrayOf(RESPONSE_PREFIX), decrypted.payload)[0]
|
val payload = parseKeys(arrayOf(RESPONSE_PREFIX), decrypted.payload)[0]
|
||||||
|
aapsLogger.info(LTag.PUMPBTCOMM, "Received decrypted response: ${payload.toHex()} in packet: $decrypted")
|
||||||
return NakResponse(payload)
|
return NakResponse(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,9 +65,9 @@ class Session(
|
||||||
source = myId,
|
source = myId,
|
||||||
destination = podId,
|
destination = podId,
|
||||||
payload = ByteArray(0),
|
payload = ByteArray(0),
|
||||||
eqos = 1,
|
eqos = 0,
|
||||||
ack = true,
|
ack = true,
|
||||||
ackNumber = response.sequenceNumber.inc()
|
ackNumber = (response.sequenceNumber.toInt()+1).toByte()
|
||||||
)
|
)
|
||||||
return enDecrypt.encrypt((msg))
|
return enDecrypt.encrypt((msg))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue