Skip to content

Commit

Permalink
dash/ble: support both 1 and 2 byte command
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
avereha committed Mar 8, 2021
1 parent db51b76 commit c337b52
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class BleCommandFail : BleCommand(BleCommandType.FAIL)

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(
byteArrayOf(type.value) + payload
Expand All @@ -36,4 +36,5 @@ open class BleCommand(val data: ByteArray) {
override fun hashCode(): Int {
return data.contentHashCode()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ enum class BleCommandType(val value: Byte) {
ABORT(0x03.toByte()),
SUCCESS(0x04.toByte()),
FAIL(0x05.toByte()),
HELLO(
0x06.toByte()
);
HELLO(0x06.toByte());

companion object {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class EnDecrypt(private val aapsLogger: AAPSLogger, private val nonce: Nonce, pr
)
val decryptedPayload = ByteArray(payload.size - MAC_SIZE)
cipher.processPacket(payload, 0, payload.size, decryptedPayload, 0)
aapsLogger.debug(LTag.PUMPBTCOMM, "Decrypted payload ${decryptedPayload.toHex()}")
return msg.copy(payload = decryptedPayload)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.CharacteristicType
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

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.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandRTS().data)
val expectCTS = bleIO.receivePacket(CharacteristicType.CMD)
if (BleCommand(expectCTS) != BleCommandCTS()) {
if (expectCTS.isEmpty()) {
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()
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending message: ${payload.toHex()}")
val splitter = PayloadSplitter(payload)
Expand All @@ -29,17 +46,18 @@ class MessageIO(private val aapsLogger: AAPSLogger, private val bleIO: BleIO) {
}
// TODO: peek for NACKs
val expectSuccess = bleIO.receivePacket(CharacteristicType.CMD)
if (BleCommand(expectSuccess) != BleCommandSuccess()) {
throw UnexpectedCommandException(BleCommand(expectSuccess))
}
expectCommandType(BleCommand(expectSuccess), BleCommandSuccess())
// TODO: handle NACKS/FAILS/etc
return null
}

fun receiveMessage(): MessagePacket {
val expectRTS = bleIO.receivePacket(CharacteristicType.CMD)
if (BleCommand(expectRTS) != BleCommandRTS()) {
throw UnexpectedCommandException(BleCommand(expectRTS))
// TODO: use higher timeout when receiving the first packet in a message
fun receiveMessage( firstCmd: ByteArray? = null): MessagePacket {
var expectRTS = firstCmd
if (expectRTS == null) {
expectRTS = bleIO.receivePacket(CharacteristicType.CMD)
}
expectCommandType(BleCommand(expectRTS), BleCommandRTS())
bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandCTS().data)
try {
val joiner = PayloadJoiner(bleIO.receivePacket(CharacteristicType.DATA))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,30 @@ class Session(
*/
fun sendCommand(cmd: Command): Response {
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)
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 decrypted = enDecrypt.decrypt(responseMsg)
aapsLogger.debug(LTag.PUMPBTCOMM, "Received response: $decrypted")
val response = parseResponse(decrypted)

sessionKeys.msgSequenceNumber++
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)
return response
}

private fun parseResponse(decrypted: MessagePacket): Response {

val payload = parseKeys(arrayOf(RESPONSE_PREFIX), decrypted.payload)[0]
aapsLogger.info(LTag.PUMPBTCOMM, "Received decrypted response: ${payload.toHex()} in packet: $decrypted")
return NakResponse(payload)
}

Expand All @@ -61,9 +65,9 @@ class Session(
source = myId,
destination = podId,
payload = ByteArray(0),
eqos = 1,
eqos = 0,
ack = true,
ackNumber = response.sequenceNumber.inc()
ackNumber = (response.sequenceNumber.toInt()+1).toByte()
)
return enDecrypt.encrypt((msg))
}
Expand Down

0 comments on commit c337b52

Please sign in to comment.