dash ble: detekt

This commit is contained in:
Andrei Vereha 2021-04-04 16:06:27 +02:00
parent c1426941cf
commit 6d2d5a7e76
7 changed files with 98 additions and 106 deletions

View file

@ -148,6 +148,7 @@ class OmnipodDashPumpPlugin @Inject constructor(
it == mapProfileToBasalProgram(profile)
} ?: true
override fun lastDataTime(): Long {
return podStateManager.lastConnection
}

View file

@ -46,9 +46,7 @@ class OmnipodDashBleManagerImpl @Inject constructor(
throw BusyException()
}
try {
val conn = connection ?: throw NotConnectedException("Not connected")
val session = conn.session ?: throw NotConnectedException("Missing session")
val session = assertSessionEstablished()
emitter.onNext(PodEvent.CommandSending(cmd))
when (session.sendCommand(cmd)) {
@ -84,6 +82,12 @@ class OmnipodDashBleManagerImpl @Inject constructor(
}
}
private fun assertSessionEstablished(): Session {
val conn = assertConnected()
return conn.session
?: throw NotConnectedException("Missing session")
}
override fun getStatus(): ConnectionStatus {
// TODO is this used?
var s: ConnectionStatus
@ -135,8 +139,9 @@ class OmnipodDashBleManagerImpl @Inject constructor(
}
private fun establishSession(msgSeq: Byte) {
val conn = connection ?: throw FailedToConnectException("connection lost")
val ltk: ByteArray = podState.ltk ?: throw FailedToConnectException("Missing LTK, activate the pod first")
val conn = assertConnected()
val ltk = assertPaired()
val uniqueId = podState.uniqueId
val podId = uniqueId?.let { Id.fromLong(uniqueId) }
@ -149,7 +154,7 @@ class OmnipodDashBleManagerImpl @Inject constructor(
if (newSqn != null) {
aapsLogger.info(LTag.PUMPBTCOMM, "Updating EAP SQN to: $newSqn")
podState.eapAkaSequenceNumber = newSqn.toLong()
var newSqn = conn.establishSession(ltk, msgSeq, myId, podId, podState.increaseEapAkaSequenceNumber())
newSqn = conn.establishSession(ltk, msgSeq, myId, podId, podState.increaseEapAkaSequenceNumber())
if (newSqn != null) {
throw SessionEstablishmentException("Received resynchronization SQN for the second time")
}
@ -158,6 +163,16 @@ class OmnipodDashBleManagerImpl @Inject constructor(
podState.commitEapAkaSequenceNumber()
}
private fun assertPaired(): ByteArray {
return podState.ltk
?: throw FailedToConnectException("Missing LTK, activate the pod first")
}
private fun assertConnected(): Connection {
return connection
?: throw FailedToConnectException("connection lost")
}
override fun pairNewPod(): Observable<PodEvent> = Observable.create { emitter ->
if (!busy.compareAndSet(false, true)) {
throw BusyException()

View file

@ -15,7 +15,7 @@ data class MessagePacket(
val sequenceNumber: Byte,
val ack: Boolean = false,
val ackNumber: Byte = 0.toByte(),
val eqos: Short = 0.toShort(), // TODO: understand. Seems to be set to 1 for commands
val eqos: Short = 0.toShort(),
val priority: Boolean = false,
val lastMessage: Boolean = false,
val gateway: Boolean = false,

View file

@ -42,7 +42,7 @@ class PayloadJoiner(private val firstPacket: ByteArray) {
oneExtraPacket = lastPacket.oneExtraPacket
}
idx > fullFragments && oneExtraPacket -> {
idx == fullFragments+1 && oneExtraPacket -> {
fragments.add(LastOptionalPlusOneBlePacket.parse(packet))
}

View file

@ -6,29 +6,11 @@ import java.util.zip.CRC32
internal class PayloadSplitter(private val payload: ByteArray) {
fun splitInPackets(): List<BlePacket> {
if (payload.size <= FirstBlePacket.CAPACITY_WITH_THE_OPTIONAL_PLUS_ONE_PACKET) {
return splitInOnePacket()
}
val ret = ArrayList<BlePacket>()
val crc32 = payload.crc32()
if (payload.size <= FirstBlePacket.CAPACITY_WITH_THE_OPTIONAL_PLUS_ONE_PACKET) {
val end = min(FirstBlePacket.CAPACITY_WITHOUT_MIDDLE_PACKETS, payload.size)
ret.add(
FirstBlePacket(
fullFragments = 0,
payload = payload.copyOfRange(0, end),
size = payload.size.toByte(),
crc32 = crc32
)
)
if (payload.size > FirstBlePacket.CAPACITY_WITHOUT_MIDDLE_PACKETS) {
ret.add(
LastOptionalPlusOneBlePacket(
index = 1,
payload = payload.copyOfRange(end, payload.size),
size = (payload.size - end).toByte()
)
)
}
return ret
}
val middleFragments = (payload.size - FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS) / MiddleBlePacket.CAPACITY
val rest =
(
@ -42,17 +24,10 @@ internal class PayloadSplitter(private val payload: ByteArray) {
)
)
for (i in 1..middleFragments) {
val p = if (i == 1) {
payload.copyOfRange(
FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS,
FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + MiddleBlePacket.CAPACITY
)
} else {
payload.copyOfRange(
FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + (i - 1) * MiddleBlePacket.CAPACITY,
FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + i * MiddleBlePacket.CAPACITY
)
}
val p = payload.copyOfRange(
FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + (i - 1) * MiddleBlePacket.CAPACITY,
FirstBlePacket.CAPACITY_WITH_MIDDLE_PACKETS + i * MiddleBlePacket.CAPACITY
)
ret.add(
MiddleBlePacket(
index = i.toByte(),
@ -88,6 +63,30 @@ internal class PayloadSplitter(private val payload: ByteArray) {
}
return ret
}
private fun splitInOnePacket(): List<BlePacket> {
val ret = ArrayList<BlePacket>()
val crc32 = payload.crc32()
val end = min(FirstBlePacket.CAPACITY_WITHOUT_MIDDLE_PACKETS, payload.size)
ret.add(
FirstBlePacket(
fullFragments = 0,
payload = payload.copyOfRange(0, end),
size = payload.size.toByte(),
crc32 = crc32
)
)
if (payload.size > FirstBlePacket.CAPACITY_WITHOUT_MIDDLE_PACKETS) {
ret.add(
LastOptionalPlusOneBlePacket(
index = 1,
payload = payload.copyOfRange(end, payload.size),
size = (payload.size - end).toByte()
)
)
}
return ret
}
}
internal fun ByteArray.crc32(): Long {

View file

@ -29,29 +29,57 @@ internal class LTKExchanger(
@Throws(PairingException::class)
fun negotiateLTK(): PairResult {
val sp1sp2 = sp1sp2(podId.address, sp2())
throwOnSendError(sp1sp2.messagePacket, "SP1SP2")
val sp1sp2 = PairMessage(
sequenceNumber = seq,
source = myId,
destination = podAddress,
keys = arrayOf(SP1, SP2),
payloads = arrayOf(podId.address, sp2())
)
throwOnSendError(sp1sp2.messagePacket, SP1+SP2)
seq++
val sps1 = sps1()
throwOnSendError(sps1.messagePacket, "SP1")
val sps1 = PairMessage(
sequenceNumber = seq,
source = myId,
destination = podAddress,
keys = arrayOf(SPS1),
payloads = arrayOf(keyExchange.pdmPublic + keyExchange.pdmNonce)
)
throwOnSendError(sps1.messagePacket, SPS1)
val podSps1 = msgIO.receiveMessage() ?: throw PairingException("Could not read SPS1")
processSps1FromPod(podSps1)
// now we have all the data to generate: confPod, confPdm, ltk and noncePrefix
seq++
val sps2 = sps2()
throwOnSendError(sps2.messagePacket, "SPS2")
val sps2 = PairMessage(
sequenceNumber = seq,
source = myId,
destination = podAddress,
keys = arrayOf(SPS2),
payloads = arrayOf(keyExchange.pdmConf)
)
throwOnSendError(sps2.messagePacket, SPS2)
val podSps2 = msgIO.receiveMessage() ?: throw PairingException("Could not read SPS2")
validatePodSps2(podSps2)
// No exception throwing after this point. It is possible that the pod saved the LTK
seq++
// send SP0GP0
throwOnSendErrorSending(sp0gp0().messagePacket, "SP0GP0")
val sp0gp0 = PairMessage (
sequenceNumber = seq,
source = myId,
destination = podAddress,
keys = arrayOf(SP0GP0),
payloads = arrayOf(ByteArray(0))
)
val result = msgIO.sendMessage(sp0gp0.messagePacket)
if (result !is MessageSendSuccess) {
aapsLogger.warn(LTag.PUMPBTCOMM,"Error sending SP0GP0: $result")
}
// No exception throwing after this point. It is possible that the pod saved the LTK
msgIO.receiveMessage()
?.let { validateP0(it) }
?: aapsLogger.warn(LTag.PUMPBTCOMM, "Could not read P0")
@ -70,39 +98,6 @@ internal class LTKExchanger(
}
}
@Throws(PairingException::class)
private fun throwOnSendErrorSending(msg: MessagePacket, msgType: String) {
val result = msgIO.sendMessage(msg)
if (result is MessageSendErrorSending) {
throw PairingException("Could not send $msgType: $result")
}
}
private fun sp1sp2(sp1: ByteArray, sp2: ByteArray): PairMessage {
val payload = StringLengthPrefixEncoding.formatKeys(
arrayOf(SP1, SP2),
arrayOf(sp1, sp2)
)
return PairMessage(
sequenceNumber = seq,
source = myId,
destination = podAddress,
payload = payload
)
}
private fun sps1(): PairMessage {
val payload = StringLengthPrefixEncoding.formatKeys(
arrayOf("SPS1="),
arrayOf(keyExchange.pdmPublic + keyExchange.pdmNonce)
)
return PairMessage(
sequenceNumber = seq,
source = myId,
destination = podAddress,
payload = payload
)
}
private fun processSps1FromPod(msg: MessagePacket) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Received SPS1 from pod: ${msg.payload.toHex()}")
@ -111,19 +106,6 @@ internal class LTKExchanger(
keyExchange.updatePodPublicData(payload)
}
private fun sps2(): PairMessage {
val payload = StringLengthPrefixEncoding.formatKeys(
arrayOf(SPS2),
arrayOf(keyExchange.pdmConf)
)
return PairMessage(
sequenceNumber = seq,
source = myId,
destination = podAddress,
payload = payload
)
}
private fun validatePodSps2(msg: MessagePacket) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Received SPS2 from pod: ${msg.payload.toHex()}")
@ -142,16 +124,6 @@ internal class LTKExchanger(
return GET_POD_STATUS_HEX_COMMAND.hexStringToByteArray()
}
private fun sp0gp0(): PairMessage {
val payload = SP0GP0.toByteArray()
return PairMessage(
sequenceNumber = seq,
source = myId,
destination = podAddress,
payload = payload
)
}
private fun validateP0(msg: MessagePacket) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Received P0 from pod: ${msg.payload.toHex()}")

View file

@ -3,17 +3,22 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.pair
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Id
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessagePacket
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessageType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.StringLengthPrefixEncoding
data class PairMessage(
val sequenceNumber: Byte,
val source: Id,
val destination: Id,
val payload: ByteArray,
private val keys: Array<String>,
private val payloads: Array<ByteArray>,
val messagePacket: MessagePacket = MessagePacket(
type = MessageType.PAIRING,
source = source,
destination = destination,
payload = payload,
payload = StringLengthPrefixEncoding.formatKeys(
keys,
payloads,
),
sequenceNumber = sequenceNumber,
sas = true // TODO: understand why this is true for PairMessages
)