Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 22 additions & 48 deletions OmniBLE/Bluetooth/Id.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,16 @@ import Foundation

class Id: Equatable {

static private let PERIPHERAL_NODE_INDEX: UInt8 = 1

static func fromInt(_ v: Int) -> Id {
return Id(Data(bigEndian: v).subdata(in: 4..<8))
}

static func fromLong(_ v: UInt32) -> Id {
static func fromUInt32(_ v: UInt32) -> Id {
return Id(Data(bigEndian: v))
}


let address: Data

init(_ address: Data) {
guard address.count == 4 else {
// TODO: Should probably throw an error here.
Expand All @@ -33,57 +30,34 @@ class Id: Equatable {
self.address = address
}

/**
* Used to obtain podId from controllerId
* The original PDM seems to rotate over 3 Ids:
* controllerID+1, controllerID+2 and controllerID+3
*/
func increment() -> Id {
var nodeId = address

//Zero out last 2 bits on right which would round down in sequence of {4, 8, 12, 16, 20, ...}
nodeId[3] = UInt8(Int(nodeId[3]) & -4)

//Increment by adding 1
nodeId[3] = nodeId[3] | Id.PERIPHERAL_NODE_INDEX
return Id(nodeId)
}

/*
TODO: the above implementation is ported from AndroidAPS while we implemented the version below.
It is not clear if skipping every 4 numbers above is intentional or a bug. It would be preferred to use the
AndroidAPS version though until we can successfully pair so we can send identical data payloads.
*/
/*
func increment() -> Id {
var val = address.toBigEndian(Int.self)
val += 1
if (val >= 4246) {
val = 4243
}
return Id.fromInt(val)
}
*/

// TODO:
// override func toString(): String {
// val asInt = ByteBuffer.wrap(address).int
// return "$asInt/${address.toHex()}"
// }

func toInt64() -> Int64 {
return address.toBigEndian(Int64.self)
}


func toUInt32() -> UInt32 {
return address.toBigEndian(UInt32.self)
}


//MARK: Comparable


// MARK: Comparable

static func == (lhs: Id, rhs: Id) -> Bool {
return lhs.address == rhs.address
}
}

// The Dash PDM uses the PDM's SN << 2 for the bottom 5 nibbles and some
// unknown values for the top 3 nibbles of its fixed 32-bit controller ID.
func createControllerId() -> UInt32 {
// Use 0x17 for top byte to be similar to, but different from, Eros's 0x1F.
return 0x17000000 | ((arc4random() & 0x003FFFFF) << 2)
}

// podId's cycle between 3 #'s of controllerId+1, +2, +3, +1, ...
func nextPodId(lastPodId: UInt32) -> UInt32 {
if (lastPodId & 0b11) == 0b11 {
// start over at controllerId + 1
return (lastPodId & ~0b11) + 1
}
// return the next sequential podId #
return lastPodId + 1
}
34 changes: 24 additions & 10 deletions OmniBLE/Bluetooth/Ids.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,36 @@

import Foundation

let CONTROLLER_ID: Int = 4242
let CONTROLLER_ID: UInt32 = 0x1092 // fixed AAPS controller Id #
let POD_ID_NOT_ACTIVATED = Data(hexadecimalString: "FFFFFFFE")!

public class Ids {

static func notActivated() -> Id {
return Id(POD_ID_NOT_ACTIVATED)
}
static func controllerId() -> Id {
return Id.fromInt(CONTROLLER_ID)

private let controllerId: Id
private let currentPodId: Id

var myId: Id {
return controllerId
}

var podId: Id {
return currentPodId
}

var myIdAddr: UInt32 {
return controllerId.toUInt32()
}
let myId: Id
let podId: Id

init(podState: PodState?) {
myId = Id.fromInt(CONTROLLER_ID)
let uniqueId = podState != nil ? Id.fromLong(podState!.address) : myId
podId = uniqueId.increment()

var podIdAddr: UInt32 {
return currentPodId.toUInt32()
}

init(myId: UInt32, podId: UInt32) {
controllerId = Id.fromUInt32(myId)
currentPodId = Id.fromUInt32(podId)
}
}
6 changes: 3 additions & 3 deletions OmniBLE/Bluetooth/MessagePacket.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ struct MessagePacket {
let sas: Bool // TODO: understand, seems to always be true
let tfs: Bool // TODO: understand, seems to be false
let version: Int16
init(type: MessageType, source: UInt32 = Ids.controllerId().toUInt32(), destination: UInt32, payload: Data, sequenceNumber: UInt8, ack: Bool = false, ackNumber: UInt8 = 0, eqos: Int16 = 0, priority: Bool = false, lastMessage: Bool = false, gateway: Bool = false, sas: Bool = true, tfs: Bool = false, version: Int16 = 0) {
init(type: MessageType, source: UInt32, destination: UInt32, payload: Data, sequenceNumber: UInt8, ack: Bool = false, ackNumber: UInt8 = 0, eqos: Int16 = 0, priority: Bool = false, lastMessage: Bool = false, gateway: Bool = false, sas: Bool = true, tfs: Bool = false, version: Int16 = 0) {
self.type = type
self.source = Id.fromLong(source)
self.destination = Id.fromLong(destination)
self.source = Id.fromUInt32(source)
self.destination = Id.fromUInt32(destination)
self.payload = payload
self.sequenceNumber = sequenceNumber
self.ack = ack
Expand Down
1 change: 1 addition & 0 deletions OmniBLE/Bluetooth/Pair/PairMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct PairMessage {
self.payloads = payloads
message = MessagePacket(
type: MessageType.PAIRING,
source: source.toUInt32(),
destination: destination.toUInt32(),
payload: StringLengthPrefixEncoding.formatKeys(
keys: keys,
Expand Down
11 changes: 6 additions & 5 deletions OmniBLE/Bluetooth/PeripheralManager+OmniBLE.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ struct MessageSendSuccess: MessageResult {
extension PeripheralManager {

/// - Throws: PeripheralManagerError
func sendHello(_ controllerId: Data) throws {
func sendHello(myId: UInt32) throws {
dispatchPrecondition(condition: .onQueue(queue))


let controllerId = Id.fromUInt32(myId).address
log.default("Sending Hello %{public}@", controllerId.hexadecimalString)
guard let characteristic = peripheral.getCommandCharacteristic() else {
throw PeripheralManagerError.notReady
Expand Down Expand Up @@ -109,7 +110,7 @@ extension PeripheralManager {
packet = try MessagePacket.parse(payload: fullPayload)
}
catch {
log.default("Error reading message: %{public}@", error.localizedDescription)
log.error("Error reading message: %{public}@", error.localizedDescription)
try? sendCommandType(PodCommand.NACK)
throw PeripheralManagerError.incorrectResponse
}
Expand Down Expand Up @@ -162,7 +163,7 @@ extension PeripheralManager {
let value = cmdQueue.remove(at: 0)

if command.rawValue != value[0] {
log.default("Data Wrong command.rawValue (%d != %d).", command.rawValue, value[0])
log.error("Data Wrong command.rawValue != value[0] (%d != %d).", command.rawValue, value[0])
throw PeripheralManagerError.incorrectResponse
}
return
Expand Down Expand Up @@ -204,7 +205,7 @@ extension PeripheralManager {
let data = dataQueue.remove(at: 0)

if (data[0] != sequence) {
log.default("Data Wrong data[0] (%d != %d).", data[0], sequence)
log.error("Data Wrong data[0] != sequence (%d != %d).", data[0], sequence)
throw PeripheralManagerError.incorrectResponse
}
return data
Expand Down
11 changes: 8 additions & 3 deletions OmniBLE/Bluetooth/PeripheralManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ class PeripheralManager: NSObject {
}

var dataQueue: [Data] = []
var dataEvent: (() -> Void)?
var cmdQueue: [Data] = []
var cmdEvent: (() -> Void)?
let queueLock = NSCondition()

/// The dispatch queue used to serialize operations on the peripheral
Expand Down Expand Up @@ -128,7 +126,7 @@ extension PeripheralManager {

self.log.default("Peripheral configuration completed")
} catch let error {
self.log.error("Error applying peripheral configuration: %@", String(describing: error))
self.log.error("Error applying peripheral configuration: %{public}@", String(describing: error))
// Will retry
}
}
Expand Down Expand Up @@ -460,6 +458,13 @@ extension PeripheralManager: CBCentralManagerDelegate {
self.log.debug("PeripheralManager - didConnect: %@", peripheral)
switch peripheral.state {
case .connected:
queueLock.lock()
if cmdQueue.count > 0 {
self.log.default("Removing %{public}d leftover elements from command queue", cmdQueue.count)
cmdQueue.removeAll()
}
queueLock.unlock()

self.log.debug("PeripheralManager - didConnect - running assertConfiguration")
assertConfiguration()
default:
Expand Down
14 changes: 9 additions & 5 deletions OmniBLE/Bluetooth/Session/SessionEstablisher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class SessionEstablisher {
private let manager: PeripheralManager
private let ltk: Data
private let eapSqn: Data
private let address: UInt32
private let myId: UInt32
private let podId: UInt32
private var msgSeq: Int

private var controllerIV: Data
Expand All @@ -34,7 +35,7 @@ class SessionEstablisher {
private let milenage: Milenage
private let log = OSLog(category: "SessionEstablisher")

init(manager: PeripheralManager, ltk: Data, eapSqn: Int, address: UInt32, msgSeq: Int) throws {
init(manager: PeripheralManager, ltk: Data, eapSqn: Int, myId: UInt32, podId: UInt32, msgSeq: Int) throws {
// guard eapSqn.count == 6 else { throw SessionEstablishmentException.InvalidParameter("EAP-SQN has to be 6 bytes long") }
guard ltk.count == 16 else { throw SessionEstablishmentException.InvalidParameter("LTK has to be 16 bytes long") }

Expand All @@ -44,7 +45,8 @@ class SessionEstablisher {
self.manager = manager
self.ltk = ltk
self.eapSqn = Data(bigEndian: eapSqn).subdata(in: 2..<8)
self.address = address
self.myId = myId
self.podId = podId
self.msgSeq = msgSeq
self.milenage = try Milenage(k: ltk, sqn: self.eapSqn)
}
Expand Down Expand Up @@ -93,7 +95,8 @@ class SessionEstablisher {
)
return MessagePacket(
type: MessageType.SESSION_ESTABLISHMENT,
destination: address,
source: myId,
destination: podId,
payload: eapMsg.toData(),
sequenceNumber: UInt8(msgSeq)
)
Expand Down Expand Up @@ -192,7 +195,8 @@ class SessionEstablisher {

return MessagePacket(
type: MessageType.SESSION_ESTABLISHMENT,
destination: address,
source: myId,
destination: podId,
payload: eapMsg.toData(),
sequenceNumber: UInt8(msgSeq)
)
Expand Down
36 changes: 27 additions & 9 deletions OmniBLE/PumpManager/MessageTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ public struct MessageTransportState: Equatable, RawRepresentable {

public var ck: Data?
public var noncePrefix: Data?
public var msgSeq: Int // 8-bit Dash MessagePacket sequence #
public var nonceSeq: Int
public var messageNumber: Int // 4-bit Omnipod Message #
public var eapSeq: Int // per session sequence #
public var msgSeq: Int // 8-bit Dash MessagePacket sequence # (with ck)
public var nonceSeq: Int // nonce sequence # (with noncePrefix)
public var messageNumber: Int // 4-bit Omnipod Message # (for Omnipod command/responses Messages)

init(ck: Data?, noncePrefix: Data?, msgSeq: Int = 0, nonceSeq: Int = 0, messageNumber: Int = 0) {
init(ck: Data?, noncePrefix: Data?, eapSeq: Int = 1, msgSeq: Int = 0, nonceSeq: Int = 0, messageNumber: Int = 0) {
self.ck = ck
self.noncePrefix = noncePrefix
self.eapSeq = eapSeq
self.msgSeq = msgSeq
self.nonceSeq = nonceSeq
self.messageNumber = messageNumber
Expand All @@ -46,6 +48,7 @@ public struct MessageTransportState: Equatable, RawRepresentable {
}
self.ck = Data(hex: ckString)
self.noncePrefix = Data(hex: noncePrefixString)
self.eapSeq = rawValue["eapSeq"] as? Int ?? 1
self.msgSeq = msgSeq
self.nonceSeq = nonceSeq
self.messageNumber = messageNumber
Expand All @@ -55,6 +58,7 @@ public struct MessageTransportState: Equatable, RawRepresentable {
return [
"ck": ck?.hexadecimalString ?? "",
"noncePrefix": noncePrefix?.hexadecimalString ?? "",
"eapSeq": eapSeq,
"msgSeq": msgSeq,
"nonceSeq": nonceSeq,
"messageNumber": messageNumber
Expand All @@ -69,6 +73,7 @@ extension MessageTransportState: CustomDebugStringConvertible {
"## MessageTransportState",
"ck: " + (ck != nil ? ck!.hexadecimalString : "nil"),
"noncePrefix: " + (noncePrefix != nil ? noncePrefix!.hexadecimalString : "nil"),
"eapSeq: \(eapSeq)",
"msgSeq: \(msgSeq)",
"nonceSeq: \(nonceSeq)",
"messageNumber: \(messageNumber)",
Expand Down Expand Up @@ -103,7 +108,7 @@ class PodMessageTransport: MessageTransport {

private let log = OSLog(category: "PodMessageTransport")

private var state: MessageTransportState {
private(set) var state: MessageTransportState {
didSet {
self.delegate?.messageTransport(self, didUpdate: state)
}
Expand All @@ -127,6 +132,15 @@ class PodMessageTransport: MessageTransport {
}
}

private(set) var eapSeq: Int {
get {
return state.eapSeq
}
set {
state.eapSeq = newValue
}
}

private(set) var msgSeq: Int {
get {
return state.msgSeq
Expand Down Expand Up @@ -154,14 +168,16 @@ class PodMessageTransport: MessageTransport {
}
}

private let address: UInt32
private let myId: UInt32
private let podId: UInt32

weak var messageLogger: MessageLogger?
weak var delegate: MessageTransportDelegate?

init(manager: PeripheralManager, address: UInt32, state: MessageTransportState) {
init(manager: PeripheralManager, myId: UInt32, podId: UInt32, state: MessageTransportState) {
self.manager = manager
self.address = address
self.myId = myId
self.podId = podId
self.state = state

guard let noncePrefix = self.noncePrefix, let ck = self.ck else { return }
Expand Down Expand Up @@ -222,7 +238,8 @@ class PodMessageTransport: MessageTransport {

let msg = MessagePacket(
type: MessageType.ENCRYPTED,
destination: self.address,
source: self.myId,
destination: self.podId,
payload: wrapped,
sequenceNumber: UInt8(msgSeq),
eqos: 1
Expand Down Expand Up @@ -316,6 +333,7 @@ extension PodMessageTransport: CustomDebugStringConvertible {
"## PodMessageTransport",
"ck: " + (ck != nil ? ck!.hexadecimalString : "nil"),
"noncePrefix: " + (noncePrefix != nil ? noncePrefix!.hexadecimalString : "nil"),
"eapSeq: \(eapSeq)",
"msgSeq: \(msgSeq)",
"nonceSeq: \(nonceSeq)",
"messageNumber: \(messageNumber)",
Expand Down
Loading