dash: start using podState for BLE
implement disconnect() various fixes after testing with a real pod(cmd is 2 bytes, message joining, etc)
This commit is contained in:
parent
4046828567
commit
e7a9e24093
11 changed files with 153 additions and 75 deletions
|
@ -36,5 +36,8 @@ data class Id(val address: ByteArray) {
|
|||
fun fromInt(v: Int): Id {
|
||||
return Id(ByteBuffer.allocate(4).putInt(v).array())
|
||||
}
|
||||
fun fromLong(v: Long): Id {
|
||||
return Id(ByteBuffer.allocate(8).putLong(v).array().copyOfRange(4,8))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,13 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm
|
|||
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothGatt
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.BluetoothProfile
|
||||
import android.content.Context
|
||||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.BuildConfig
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.callbacks.BleCommCallbacks
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.command.BleCommandHello
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.endecrypt.EnDecrypt
|
||||
|
@ -16,13 +18,13 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.io.Chara
|
|||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessageIO
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.pair.LTKExchanger
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.scan.PodScanner
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.EapSqn
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.Session
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.SessionEstablisher
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session.SessionKeys
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.status.ConnectionStatus
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.event.PodEvent
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager
|
||||
import info.nightscout.androidaps.utils.extensions.toHex
|
||||
import io.reactivex.Observable
|
||||
import java.util.concurrent.BlockingQueue
|
||||
|
@ -34,7 +36,8 @@ import javax.inject.Singleton
|
|||
@Singleton
|
||||
class OmnipodDashBleManagerImpl @Inject constructor(
|
||||
private val context: Context,
|
||||
private val aapsLogger: AAPSLogger
|
||||
private val aapsLogger: AAPSLogger,
|
||||
private val podState: OmnipodDashPodStateManager
|
||||
) : OmnipodDashBleManager {
|
||||
|
||||
private val bluetoothManager: BluetoothManager =
|
||||
|
@ -42,6 +45,8 @@ class OmnipodDashBleManagerImpl @Inject constructor(
|
|||
private val bluetoothAdapter: BluetoothAdapter = bluetoothManager.adapter
|
||||
private var sessionKeys: SessionKeys? = null
|
||||
private var msgIO: MessageIO? = null
|
||||
private var gatt: BluetoothGatt? = null
|
||||
private var status: ConnectionStatus = ConnectionStatus.IDLE
|
||||
|
||||
@Throws(
|
||||
FailedToConnectException::class,
|
||||
|
@ -54,30 +59,29 @@ class OmnipodDashBleManagerImpl @Inject constructor(
|
|||
DescriptorNotFoundException::class,
|
||||
CouldNotConfirmDescriptorWriteException::class
|
||||
)
|
||||
private fun connect(podAddress: String): BleIO {
|
||||
// TODO: locking?
|
||||
val podDevice = bluetoothAdapter.getRemoteDevice(podAddress)
|
||||
private fun connect(podDevice: BluetoothDevice): BleIO {
|
||||
val incomingPackets: Map<CharacteristicType, BlockingQueue<ByteArray>> =
|
||||
mapOf(
|
||||
CharacteristicType.CMD to LinkedBlockingDeque(),
|
||||
CharacteristicType.DATA to LinkedBlockingDeque()
|
||||
)
|
||||
val bleCommCallbacks = BleCommCallbacks(aapsLogger, incomingPackets)
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to $podAddress")
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Connecting to ${podDevice.address}")
|
||||
val autoConnect = false // TODO: check what to use here
|
||||
|
||||
val gatt = podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE)
|
||||
val gattConnection = podDevice.connectGatt(context, autoConnect, bleCommCallbacks, BluetoothDevice.TRANSPORT_LE)
|
||||
bleCommCallbacks.waitForConnection(CONNECT_TIMEOUT_MS)
|
||||
val connectionState = bluetoothManager.getConnectionState(podDevice, BluetoothProfile.GATT)
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "GATT connection state: $connectionState")
|
||||
if (connectionState != BluetoothProfile.STATE_CONNECTED) {
|
||||
throw FailedToConnectException(podAddress)
|
||||
throw FailedToConnectException(podDevice.address)
|
||||
}
|
||||
val discoverer = ServiceDiscoverer(aapsLogger, gatt, bleCommCallbacks)
|
||||
val discoverer = ServiceDiscoverer(aapsLogger, gattConnection, bleCommCallbacks)
|
||||
val chars = discoverer.discoverServices()
|
||||
val bleIO = BleIO(aapsLogger, chars, incomingPackets, gatt, bleCommCallbacks)
|
||||
val bleIO = BleIO(aapsLogger, chars, incomingPackets, gattConnection, bleCommCallbacks)
|
||||
bleIO.sendAndConfirmPacket(CharacteristicType.CMD, BleCommandHello(CONTROLLER_ID).data)
|
||||
bleIO.readyToRead()
|
||||
gatt = gattConnection
|
||||
return bleIO
|
||||
}
|
||||
|
||||
|
@ -117,7 +121,11 @@ class OmnipodDashBleManagerImpl @Inject constructor(
|
|||
}
|
||||
|
||||
override fun getStatus(): ConnectionStatus {
|
||||
TODO("not implemented")
|
||||
var s: ConnectionStatus
|
||||
synchronized(status) {
|
||||
s = status
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@Throws(
|
||||
|
@ -132,50 +140,77 @@ class OmnipodDashBleManagerImpl @Inject constructor(
|
|||
DescriptorNotFoundException::class,
|
||||
CouldNotConfirmDescriptorWriteException::class
|
||||
)
|
||||
|
||||
override fun connect(): Observable<PodEvent> = Observable.create { emitter ->
|
||||
// TODO: when we are already connected,
|
||||
// emit PodEvent.AlreadyConnected, complete the observable and return from this method
|
||||
|
||||
try {
|
||||
aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation")
|
||||
if (podState.bluetoothAddress == null) {
|
||||
aapsLogger.info(LTag.PUMPBTCOMM, "starting new pod activation")
|
||||
|
||||
val podScanner = PodScanner(aapsLogger, bluetoothAdapter)
|
||||
emitter.onNext(PodEvent.Scanning)
|
||||
val podScanner = PodScanner(aapsLogger, bluetoothAdapter)
|
||||
emitter.onNext(PodEvent.Scanning)
|
||||
|
||||
val podAddress = podScanner.scanForPod(
|
||||
PodScanner.SCAN_FOR_SERVICE_UUID,
|
||||
PodScanner.POD_ID_NOT_ACTIVATED
|
||||
).scanResult.device.address
|
||||
// For tests: this.podAddress = "B8:27:EB:1D:7E:BB";
|
||||
val podAddress = podScanner.scanForPod(
|
||||
PodScanner.SCAN_FOR_SERVICE_UUID,
|
||||
PodScanner.POD_ID_NOT_ACTIVATED
|
||||
).scanResult.device.address
|
||||
// For tests: this.podAddress = "B8:27:EB:1D:7E:BB";
|
||||
podState.bluetoothAddress = podAddress
|
||||
}
|
||||
emitter.onNext(PodEvent.BluetoothConnecting)
|
||||
val podAddress = podState.bluetoothAddress ?: throw FailedToConnectException("Lost connection")
|
||||
// check if already connected
|
||||
val podDevice = bluetoothAdapter.getRemoteDevice(podAddress)
|
||||
val connectionState = bluetoothManager.getConnectionState(podDevice, BluetoothProfile.GATT)
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "GATT connection state: $connectionState")
|
||||
|
||||
val bleIO = connect(podAddress)
|
||||
emitter.onNext(PodEvent.BluetoothConnected(podAddress))
|
||||
if (connectionState == BluetoothProfile.STATE_CONNECTED) {
|
||||
podState.uniqueId ?: throw FailedToConnectException("Already connection and uniqueId is missing")
|
||||
emitter.onNext(PodEvent.AlreadyConnected(podAddress, podState.uniqueId ?: 0))
|
||||
emitter.onComplete()
|
||||
return@create
|
||||
}
|
||||
if (msgIO != null) {
|
||||
disconnect()
|
||||
}
|
||||
|
||||
val bleIO = connect(podDevice)
|
||||
val mIO = MessageIO(aapsLogger, bleIO)
|
||||
val myId = Id.fromInt(CONTROLLER_ID)
|
||||
val podId = myId.increment()
|
||||
var msgSeq = 1.toByte()
|
||||
val ltkExchanger = LTKExchanger(aapsLogger, mIO, myId, podId, Id.fromLong(PodScanner.POD_ID_NOT_ACTIVATED))
|
||||
if (podState.ltk == null) {
|
||||
emitter.onNext(PodEvent.Pairing)
|
||||
val pairResult = ltkExchanger.negotiateLTK()
|
||||
podState.ltk = pairResult.ltk
|
||||
podState.uniqueId = podId.toLong()
|
||||
msgSeq = pairResult.msgSeq
|
||||
podState.eapAkaSequenceNumber = 1
|
||||
if (BuildConfig.DEBUG) {
|
||||
aapsLogger.info(LTag.PUMPCOMM, "Got LTK: ${pairResult.ltk.toHex()}")
|
||||
}
|
||||
}
|
||||
|
||||
val ltkExchanger = LTKExchanger(aapsLogger, mIO)
|
||||
|
||||
emitter.onNext(PodEvent.Pairing)
|
||||
|
||||
val ltk = ltkExchanger.negotiateLTK()
|
||||
val ltk: ByteArray = podState.ltk!!
|
||||
|
||||
emitter.onNext(PodEvent.EstablishingSession)
|
||||
|
||||
val eapSqn = EapSqn(1)
|
||||
aapsLogger.info(LTag.PUMPCOMM, "Got LTK: ${ltk.ltk.toHex()}")
|
||||
val eapAkaExchanger = SessionEstablisher(aapsLogger, mIO, ltk, eapSqn)
|
||||
val eapSqn = podState.increaseEapAkaSequenceNumber()
|
||||
val eapAkaExchanger = SessionEstablisher(aapsLogger, mIO, ltk, eapSqn, myId, podId, msgSeq)
|
||||
val keys = eapAkaExchanger.negotiateSessionKeys()
|
||||
aapsLogger.info(LTag.PUMPCOMM, "CK: ${keys.ck.toHex()}")
|
||||
aapsLogger.info(LTag.PUMPCOMM, "msgSequenceNumber: ${keys.msgSequenceNumber}")
|
||||
aapsLogger.info(LTag.PUMPCOMM, "Nonce: ${keys.nonce}")
|
||||
podState.commitEapAkaSequenceNumber()
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
aapsLogger.info(LTag.PUMPCOMM, "CK: ${keys.ck.toHex()}")
|
||||
aapsLogger.info(LTag.PUMPCOMM, "msgSequenceNumber: ${keys.msgSequenceNumber}")
|
||||
aapsLogger.info(LTag.PUMPCOMM, "Nonce: ${keys.nonce}")
|
||||
}
|
||||
sessionKeys = keys
|
||||
msgIO = mIO
|
||||
|
||||
emitter.onNext(PodEvent.Connected(ltk.podId.toLong()))
|
||||
emitter.onNext(PodEvent.Connected(podId.toLong()))
|
||||
|
||||
emitter.onComplete()
|
||||
} catch (ex: Exception) {
|
||||
|
@ -184,7 +219,11 @@ class OmnipodDashBleManagerImpl @Inject constructor(
|
|||
}
|
||||
|
||||
override fun disconnect() {
|
||||
TODO("not implemented")
|
||||
val localGatt = gatt
|
||||
localGatt?.close()
|
||||
gatt = null
|
||||
msgIO = null
|
||||
sessionKeys = null
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -11,9 +11,10 @@ class BleCommandAbort : BleCommand(BleCommandType.ABORT)
|
|||
class BleCommandSuccess : BleCommand(BleCommandType.SUCCESS)
|
||||
|
||||
class BleCommandFail : BleCommand(BleCommandType.FAIL)
|
||||
|
||||
open class BleCommand(val data: ByteArray) {
|
||||
|
||||
constructor(type: BleCommandType) : this(byteArrayOf(type.value))
|
||||
constructor(type: BleCommandType) : this(byteArrayOf(type.value, 0))
|
||||
|
||||
constructor(type: BleCommandType, payload: ByteArray) : this(
|
||||
byteArrayOf(type.value) + payload
|
||||
|
|
|
@ -32,7 +32,7 @@ class PayloadJoiner(private val firstPacket: ByteArray) {
|
|||
fullFragments == 0 -> {
|
||||
crc = ByteBuffer.wrap(firstPacket.copyOfRange(2, 6)).int.toUnsignedLong()
|
||||
val rest = firstPacket[6]
|
||||
val end = min(rest + FirstBlePacket.HEADER_SIZE_WITHOUT_MIDDLE_PACKETS, BlePacket.MAX_SIZE)
|
||||
val end = min(rest + FirstBlePacket.HEADER_SIZE_WITHOUT_MIDDLE_PACKETS, firstPacket.size)
|
||||
oneExtraPacket = rest + FirstBlePacket.HEADER_SIZE_WITHOUT_MIDDLE_PACKETS > end
|
||||
if (end > firstPacket.size) {
|
||||
throw IncorrectPacketException(0, firstPacket)
|
||||
|
@ -78,12 +78,12 @@ class PayloadJoiner(private val firstPacket: ByteArray) {
|
|||
}
|
||||
crc = ByteBuffer.wrap(packet.copyOfRange(2, 6)).int.toUnsignedLong()
|
||||
val rest = packet[1].toInt()
|
||||
val end = min(rest + LastBlePacket.HEADER_SIZE, BlePacket.MAX_SIZE)
|
||||
val end = min(rest + LastBlePacket.HEADER_SIZE, packet.size)
|
||||
oneExtraPacket = rest + LastBlePacket.HEADER_SIZE > end
|
||||
if (packet.size < end) {
|
||||
throw IncorrectPacketException(idx.toByte(), packet)
|
||||
}
|
||||
fragments.add(packet.copyOfRange(LastBlePacket.HEADER_SIZE, packet.size))
|
||||
fragments.add(packet.copyOfRange(LastBlePacket.HEADER_SIZE, end))
|
||||
}
|
||||
|
||||
idx > fullFragments -> { // this is the extra fragment
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.spongycastle.crypto.macs.CMac
|
|||
import org.spongycastle.crypto.params.KeyParameter
|
||||
import java.security.SecureRandom
|
||||
|
||||
internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgIO: MessageIO) {
|
||||
internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgIO: MessageIO, val myId: Id, val podId: Id, val podAddress: Id) {
|
||||
|
||||
private val pdmPrivate = X25519.generatePrivateKey()
|
||||
private val pdmPublic = X25519.publicFromPrivate(pdmPrivate)
|
||||
|
@ -27,8 +27,6 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
|||
private val pdmNonce = ByteArray(NONCE_SIZE)
|
||||
private val pdmConf = ByteArray(CMAC_SIZE)
|
||||
private val podConf = ByteArray(CMAC_SIZE)
|
||||
private val controllerId = Id.fromInt(OmnipodDashBleManagerImpl.CONTROLLER_ID)
|
||||
val nodeId = controllerId.increment()
|
||||
private var seq: Byte = 1
|
||||
private var ltk = ByteArray(CMAC_SIZE)
|
||||
|
||||
|
@ -39,7 +37,7 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
|||
|
||||
fun negotiateLTK(): PairResult {
|
||||
// send SP1, SP2
|
||||
val sp1sp2 = sp1sp2(nodeId.address, sp2())
|
||||
val sp1sp2 = sp1sp2(podId.address, sp2())
|
||||
msgIO.sendMessage(sp1sp2.messagePacket)
|
||||
|
||||
seq++
|
||||
|
@ -76,7 +74,6 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
|||
|
||||
return PairResult(
|
||||
ltk = ltk,
|
||||
podId = nodeId,
|
||||
msgSeq = seq
|
||||
)
|
||||
}
|
||||
|
@ -88,8 +85,8 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
|||
)
|
||||
return PairMessage(
|
||||
sequenceNumber = seq,
|
||||
source = controllerId,
|
||||
destination = nodeId,
|
||||
source = myId,
|
||||
destination = podAddress,
|
||||
payload = payload
|
||||
)
|
||||
}
|
||||
|
@ -101,8 +98,8 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
|||
)
|
||||
return PairMessage(
|
||||
sequenceNumber = seq,
|
||||
source = controllerId,
|
||||
destination = nodeId,
|
||||
source = myId,
|
||||
destination = podAddress,
|
||||
payload = payload
|
||||
)
|
||||
}
|
||||
|
@ -125,8 +122,8 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
|||
)
|
||||
return PairMessage(
|
||||
sequenceNumber = seq,
|
||||
source = controllerId,
|
||||
destination = nodeId,
|
||||
source = myId,
|
||||
destination = podAddress,
|
||||
payload = payload
|
||||
)
|
||||
}
|
||||
|
@ -159,8 +156,8 @@ internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgI
|
|||
val payload = SP0GP0.toByteArray()
|
||||
return PairMessage(
|
||||
sequenceNumber = seq,
|
||||
source = controllerId,
|
||||
destination = nodeId,
|
||||
source = myId,
|
||||
destination = podAddress,
|
||||
payload = payload
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ 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.utils.extensions.toHex
|
||||
|
||||
data class PairResult(val ltk: ByteArray, val podId: Id, val msgSeq: Byte) {
|
||||
data class PairResult(val ltk: ByteArray, val msgSeq: Byte) {
|
||||
init {
|
||||
require(ltk.size == 16) { "LTK length must be 16 bytes. Received LTK: ${ltk.toHex()}" }
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ data class EapMessage(
|
|||
throw MessageIOException("Invalid eap payload. Expected AKA packet type: ${payload.toHex()}")
|
||||
}
|
||||
val attributesPayload = payload.copyOfRange(8, totalSize)
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "EAP attributes: ${attributesPayload.toByteString()}")
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "parsing EAP payload: ${payload.toHex()}")
|
||||
return EapMessage(
|
||||
code = EapCode.byValue(payload[0]),
|
||||
identifier = payload[1],
|
||||
|
|
|
@ -3,32 +3,33 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.session
|
|||
import info.nightscout.androidaps.logging.AAPSLogger
|
||||
import info.nightscout.androidaps.logging.LTag
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Id
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManagerImpl
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.endecrypt.Nonce
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.SessionEstablishmentException
|
||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.MessageIO
|
||||
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.pair.PairResult
|
||||
import info.nightscout.androidaps.utils.extensions.toHex
|
||||
import java.security.SecureRandom
|
||||
|
||||
class SessionEstablisher(
|
||||
private val aapsLogger: AAPSLogger,
|
||||
private val msgIO: MessageIO,
|
||||
private val ltk: PairResult,
|
||||
private val eapSqn: EapSqn
|
||||
private val ltk: ByteArray,
|
||||
private val eapSqn: ByteArray,
|
||||
private val myId: Id,
|
||||
private val podId: Id,
|
||||
private var msgSeq: Byte
|
||||
) {
|
||||
|
||||
var sequenceNumber = ltk.msgSeq
|
||||
|
||||
private val controllerIV = ByteArray(IV_SIZE)
|
||||
private var nodeIV = ByteArray(IV_SIZE)
|
||||
|
||||
private val controllerId = Id.fromInt(OmnipodDashBleManagerImpl.CONTROLLER_ID)
|
||||
private val milenage = Milenage(aapsLogger, ltk.ltk, eapSqn.increment())
|
||||
private val milenage = Milenage(aapsLogger, ltk, eapSqn)
|
||||
|
||||
init {
|
||||
require(eapSqn.size == 6) {"EAP-SQN has to be 6 bytes long"}
|
||||
require(ltk.size == 16) {"LTK has to be 16 bytes long"}
|
||||
|
||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Starting EAP-AKA")
|
||||
val random = SecureRandom()
|
||||
random.nextBytes(controllerIV)
|
||||
|
@ -36,14 +37,14 @@ class SessionEstablisher(
|
|||
|
||||
fun negotiateSessionKeys(): SessionKeys {
|
||||
// send EAP-AKA challenge
|
||||
sequenceNumber++ // TODO: get from pod state. This only works for activating a new pod
|
||||
msgSeq++ // TODO: get from pod state. This only works for activating a new pod
|
||||
var challenge = eapAkaChallenge()
|
||||
msgIO.sendMessage(challenge)
|
||||
|
||||
val challengeResponse = msgIO.receiveMessage()
|
||||
processChallengeResponse(challengeResponse) // TODO: what do we have to answer if challenge response does not validate?
|
||||
|
||||
sequenceNumber++
|
||||
msgSeq++
|
||||
var success = eapSuccess()
|
||||
msgIO.sendMessage(success)
|
||||
|
||||
|
@ -53,7 +54,7 @@ class SessionEstablisher(
|
|||
prefix = controllerIV + nodeIV,
|
||||
sqn = 0
|
||||
),
|
||||
msgSequenceNumber = sequenceNumber
|
||||
msgSequenceNumber = msgSeq
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -66,14 +67,14 @@ class SessionEstablisher(
|
|||
|
||||
val eapMsg = EapMessage(
|
||||
code = EapCode.REQUEST,
|
||||
identifier = 42, // TODO: find what value we need here, it's probably random
|
||||
identifier = 189.toByte(), // TODO: find what value we need here, it's probably random
|
||||
attributes = attributes
|
||||
)
|
||||
return MessagePacket(
|
||||
type = MessageType.SESSION_ESTABLISHMENT,
|
||||
sequenceNumber = sequenceNumber,
|
||||
source = controllerId,
|
||||
destination = ltk.podId,
|
||||
sequenceNumber = msgSeq,
|
||||
source = myId,
|
||||
destination = podId,
|
||||
payload = eapMsg.toByteArray()
|
||||
)
|
||||
}
|
||||
|
@ -103,14 +104,14 @@ class SessionEstablisher(
|
|||
val eapMsg = EapMessage(
|
||||
code = EapCode.SUCCESS,
|
||||
attributes = arrayOf(),
|
||||
identifier = 44 // TODO: find what value we need here
|
||||
identifier = 189.toByte() // TODO: find what value we need here
|
||||
)
|
||||
|
||||
return MessagePacket(
|
||||
type = MessageType.SESSION_ESTABLISHMENT,
|
||||
sequenceNumber = sequenceNumber,
|
||||
source = controllerId,
|
||||
destination = ltk.podId,
|
||||
sequenceNumber = msgSeq,
|
||||
source = myId,
|
||||
destination = podId,
|
||||
payload = eapMsg.toByteArray()
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.status
|
||||
|
||||
enum class ConnectionStatus {
|
||||
CONNECTED,
|
||||
NOT_CONNECTED;
|
||||
IDLE,
|
||||
BUSY,
|
||||
CONNECTING,
|
||||
ESTABLISHING_SESSION,
|
||||
PAIRING,
|
||||
RUNNING_COMMAND;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ interface OmnipodDashPodStateManager {
|
|||
val activationTime: Long?
|
||||
var uniqueId: Long? // TODO make Int
|
||||
var bluetoothAddress: String?
|
||||
var ltk: ByteArray?
|
||||
var eapAkaSequenceNumber: Long
|
||||
|
||||
val bluetoothVersion: SoftwareVersion?
|
||||
val firmwareVersion: SoftwareVersion?
|
||||
|
@ -46,6 +48,8 @@ interface OmnipodDashPodStateManager {
|
|||
val basalProgram: BasalProgram?
|
||||
|
||||
fun increaseMessageSequenceNumber()
|
||||
fun increaseEapAkaSequenceNumber():ByteArray
|
||||
fun commitEapAkaSequenceNumber()
|
||||
fun updateFromDefaultStatusResponse(response: DefaultStatusResponse)
|
||||
fun updateFromVersionResponse(response: VersionResponse)
|
||||
fun updateFromSetUniqueIdResponse(response: SetUniqueIdResponse)
|
||||
|
|
|
@ -13,6 +13,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.
|
|||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.VersionResponse
|
||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||
import java.io.Serializable
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
@ -150,6 +151,32 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
|||
store()
|
||||
}
|
||||
|
||||
override var eapAkaSequenceNumber: Long
|
||||
get() = podState.eapAkaSequenceNumber
|
||||
set(value) {
|
||||
podState.eapAkaSequenceNumber = value
|
||||
store()
|
||||
}
|
||||
|
||||
override var ltk: ByteArray?
|
||||
get() = podState.ltk
|
||||
set(value) {
|
||||
podState.ltk = value
|
||||
store()
|
||||
}
|
||||
|
||||
override fun increaseEapAkaSequenceNumber():ByteArray {
|
||||
podState.eapAkaSequenceNumber++
|
||||
return ByteBuffer.allocate(8)
|
||||
.putLong(podState.eapAkaSequenceNumber)
|
||||
.array()
|
||||
.copyOfRange(2, 8)
|
||||
}
|
||||
|
||||
override fun commitEapAkaSequenceNumber() {
|
||||
store()
|
||||
}
|
||||
|
||||
override fun updateFromDefaultStatusResponse(response: DefaultStatusResponse) {
|
||||
podState.deliveryStatus = response.deliveryStatus
|
||||
podState.podStatus = response.podStatus
|
||||
|
@ -262,6 +289,8 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
|
|||
var activationTime: Long? = null
|
||||
var uniqueId: Long? = null
|
||||
var bluetoothAddress: String? = null
|
||||
var ltk: ByteArray? = null
|
||||
var eapAkaSequenceNumber: Long = 1
|
||||
|
||||
var bleVersion: SoftwareVersion? = null
|
||||
var firmwareVersion: SoftwareVersion? = null
|
||||
|
|
Loading…
Reference in a new issue