WIP: sp1sp2

This commit is contained in:
Andrei Vereha 2021-02-26 16:00:20 +01:00
parent 4e6ad3f113
commit 318c0c642c
8 changed files with 165 additions and 27 deletions

View file

@ -95,7 +95,7 @@ class OmnipodDashBleManagerImpl @Inject constructor(private val context: Context
companion object {
private const val CONNECT_TIMEOUT_MS = 5000
private const val CONTROLLER_ID = 4242 // TODO read from preferences or somewhere else.
public const val CONTROLLER_ID = 4242 // TODO read from preferences or somewhere else.
}
}

View file

@ -1,35 +1,65 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.ltk
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.Address
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.OmnipodDashBleManagerImpl
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.Id
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.utils.extensions.hexStringToByteArray
import info.nightscout.androidaps.utils.extensions.toHex
import java.nio.ByteBuffer
internal class LTKExchanger(private val aapsLogger: AAPSLogger,private val msgIO: MessageIO) {
internal class LTKExchanger(private val aapsLogger: AAPSLogger, private val msgIO: MessageIO) {
fun negociateLTKAndNonce(): LTK? {
// send SP1, SP2
// TODO: get this from somewhere(preferences?)
var seq: Byte = 1
val controllerId = Id.fromInt(OmnipodDashBleManagerImpl.CONTROLLER_ID)
val nodeId = controllerId.increment()
var sp1sp2 = sp1sp2(nodeId.address, sp2(), seq, controllerId, nodeId)
msgIO.sendMesssage(sp1sp2.messagePacket)
/*
var sps1 =
msgIO.sendMesssage(sps1.messagePacket)
// send SPS1
// read SPS1
val podSps1 = msgIO.receiveMessage()
// send SPS2
var sps2 = PairMessage()
msgIO.sendMesssage(sps2.messagePacket)
// read SPS2
val podSps2 = msgIO.receiveMessage()
// send SP0GP0
msgIO.sendMesssage(sps2.messagePacket)
// read P0
val msg = MessagePacket(
destination = Address(byteArrayOf(1,2,3,4)),
source = Address(byteArrayOf(5,6,7,8)),
payload = "545710030100038002420000fffffffe5350313d0004024200032c5350323d000bffc32dbd20030e01000016".hexStringToByteArray(),
sequenceNumber = 1,
type = MessageType.PAIRING,
)
msgIO.sendMesssage(msg)
val p0 = msgIO.receiveMessage()
*/
return null
}
}
private fun sp2(): ByteArray {
// This is GetPodStatus command, with page 0 parameter.
// We could replace that in the future with the serialized GetPodStatus()
return GET_POD_STATUS_HEX_COMMAND.hexStringToByteArray()
}
fun sp1sp2(sp1: ByteArray, sp2: ByteArray, seq: Byte, controllerId: Id, nodeId: Id): PairMessage {
val payload = "SP1=".toByteArray() + sp1
",SP2=".toByteArray() + sp2
return PairMessage(
sequenceNumber = seq,
source = controllerId,
destination = nodeId,
payload = payload,
)
}
companion object {
private val GET_POD_STATUS_HEX_COMMAND = "ffc32dbd08030e0100008a" // TODO for now we are assuming this command is build out of constant parameters, use a proper command builder for that.
}
}

View file

@ -1,3 +1,21 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.ltk
class PairMessage
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message.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
data class PairMessage(
val sequenceNumber: Byte,
val source: Id,
val destination: Id,
val payload: ByteArray,
val messagePacket: MessagePacket = MessagePacket(
type=MessageType.PAIRING,
source=source,
destination = destination,
encryptedPayload=false,
payload=payload,
sequenceNumber=sequenceNumber,
sas=true, // TODO: understand why this is true for PairMessages
),
) {}

View file

@ -1,7 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
data class Address(val address: ByteArray) {
init {
require(address.size == 4)
}
}

View file

@ -0,0 +1,36 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.ltk.LTKExchanger
import info.nightscout.androidaps.utils.extensions.toHex
import java.nio.ByteBuffer
data class Id(val address: ByteArray) {
init {
require(address.size == 4)
}
/**
* Used to obtain podId from controllerId
*/
fun increment(): Id {
val nodeId = address.copyOf()
nodeId[3] = (nodeId[3].toInt() and -4).toByte()
nodeId[3] = (nodeId[3].toInt() or PERIPHERAL_NODE_INDEX).toByte()
return Id(nodeId)
}
override fun toString(): String {
val asInt = ByteBuffer.wrap(address).getInt()
return "${asInt}/${address.toHex()}"
}
companion object {
private val PERIPHERAL_NODE_INDEX = 1 // TODO: understand the meaning of this value. It comes from preferences
fun fromInt(v: Int): Id {
return Id(ByteBuffer.allocate(4).putInt(v).array())
}
}
}

View file

@ -0,0 +1,9 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
interface Message {
/**
*
*/
fun messagePacket(): MessagePacket
}

View file

@ -1,9 +1,38 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
import java.io.DataOutput
import java.nio.ByteBuffer
/***
* MessagePacket contains header and raw payload for a message
*/
class Flag:Byte{
fun set(idx: Byte, val: Boolean) {
val mask = 1 <lsh (7-idx)
}
func (f *flag) set(index byte, val bool) {
var mask flag = 1 << (7 - index)
if !val {
return
}
*f |= mask
}
func (f flag) get(index byte) byte {
var mask flag = 1 << (7 - index)
if f&mask == 0 {
return 0
}
return 1
}
}
data class MessagePacket(
val type: MessageType,
val source: Address,
val destination: Address,
val source: Id,
val destination: Id,
val payload: ByteArray,
val sequenceNumber: Byte,
val ack: Boolean = false,
@ -17,11 +46,17 @@ data class MessagePacket(
val version: Short = 0.toShort()) {
fun asByteArray(): ByteArray {
// TODO: implement proper serialization
val v = ByteBuffer.allocate(16+ payload.size)
v.put(MAGIC_PATTERN.toByteArray())
val f1: Byte=0
return this.payload
}
companion object {
private val MAGIC_PATTERN = "TW" // all messages start with this string
fun parse(payload: ByteArray): MessagePacket {
TODO("implement message header parsing")
}

View file

@ -0,0 +1,17 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
/***
* String prefix and length encoding and decoding. Example message:
*/
class StringLengthPrefixEncoding {
companion object {
fun parseKeys(keys: List<String>): List<ByteArray> {
TODO("not implemented")
}
fun formatKeys(keys: List<String>, payload: List<ByteArray>, addLength: Boolean): ByteArray {
TODO("not implemented")
}
}
}