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
11 changes: 10 additions & 1 deletion CGMBLEKit/BluetoothManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ protocol BluetoothManagerDelegate: class {
/// - manager: The bluetooth manager
/// - response: The data received on the backfill characteristic
func bluetoothManager(_ manager: BluetoothManager, didReceiveBackfillResponse response: Data)

/// Informs the delegate that the bluetooth manager received new data in the authentication characteristic
///
/// - Parameters:
/// - manager: The bluetooth manager
/// - response: The data received on the authentication characteristic
func bluetoothManager(_ manager: BluetoothManager, peripheralManager: PeripheralManager, didReceiveAuthenticationResponse response: Data)
}


Expand Down Expand Up @@ -320,12 +327,14 @@ extension BluetoothManager: PeripheralManagerDelegate {
}

switch CGMServiceCharacteristicUUID(rawValue: characteristic.uuid.uuidString.uppercased()) {
case .none, .communication?, .authentication?:
case .none, .communication?:
return
case .control?:
self.delegate?.bluetoothManager(self, didReceiveControlResponse: value)
case .backfill?:
self.delegate?.bluetoothManager(self, didReceiveBackfillResponse: value)
case .authentication?:
self.delegate?.bluetoothManager(self, peripheralManager: manager, didReceiveAuthenticationResponse: value)
}
}
}
11 changes: 10 additions & 1 deletion CGMBLEKit/BluetoothServices.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,24 @@ enum DeviceInfoCharacteristicUUID: String, CBUUIDRawValue {


enum CGMServiceCharacteristicUUID: String, CBUUIDRawValue {

// Read/Notify
case communication = "F8083533-849E-531C-C594-30F1F86A4EA5"

// Write/Indicate
case control = "F8083534-849E-531C-C594-30F1F86A4EA5"
// Read/Write/Indicate

// Write/Indicate
case authentication = "F8083535-849E-531C-C594-30F1F86A4EA5"

// Read/Write/Notify
case backfill = "F8083536-849E-531C-C594-30F1F86A4EA5"

// // Unknown attribute present on older G6 transmitters
// case unknown1 = "F8083537-849E-531C-C594-30F1F86A4EA5"
//
// // Updated G6 characteristic (read/notify)
// case unknown2 = "F8083538-849E-531C-C594-30F1F86A4EA5"
}


Expand Down
8 changes: 4 additions & 4 deletions CGMBLEKit/Messages/AuthChallengeRxMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import Foundation


struct AuthChallengeRxMessage: TransmitterRxMessage {
let authenticated: UInt8
let bonded: UInt8
let isAuthenticated: Bool
let isBonded: Bool

init?(data: Data) {
guard data.count >= 3 else {
Expand All @@ -22,7 +22,7 @@ struct AuthChallengeRxMessage: TransmitterRxMessage {
return nil
}

authenticated = data[1]
bonded = data[2]
isAuthenticated = data[1] == 0x1
isBonded = data[2] == 0x1
}
}
47 changes: 38 additions & 9 deletions CGMBLEKit/Transmitter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ public final class Transmitter: BluetoothManagerDelegate {

peripheralManager.perform { (peripheral) in
if self.passiveModeEnabled {
self.log.debug("Listening for control commands in passive mode")
self.log.debug("Listening for authentication responses in passive mode")
do {
try peripheral.listenToControl()
try peripheral.listenToCharacteristic(.authentication)
} catch let error {
self.delegateQueue.async {
self.delegate?.transmitter(self, didError: error)
Expand All @@ -162,14 +162,14 @@ public final class Transmitter: BluetoothManagerDelegate {
self.log.debug("Authenticating with transmitter")
let status = try peripheral.authenticate(id: self.id)

if status.bonded != 0x1 {
if !status.isBonded {
self.log.debug("Requesting bond")
try peripheral.requestBond()

self.log.debug("Bonding request sent. Waiting user to respond.")
}

try peripheral.enableNotify(shouldWaitForBond: status.bonded != 0x1)
try peripheral.enableNotify(shouldWaitForBond: !status.isBonded)
defer {
self.log.debug("Initiating a disconnect")
peripheral.disconnect()
Expand Down Expand Up @@ -319,6 +319,28 @@ public final class Transmitter: BluetoothManagerDelegate {

self.backfillBuffer?.append(response)
}

func bluetoothManager(_ manager: BluetoothManager, peripheralManager: PeripheralManager, didReceiveAuthenticationResponse response: Data) {

if let message = AuthChallengeRxMessage(data: response), message.isBonded, message.isAuthenticated {
self.log.debug("Observed authenticated session. enabling notifications for control characteristic.")
peripheralManager.perform { (peripheral) in
do {
try peripheral.listenToCharacteristic(.control)
try peripheral.listenToCharacteristic(.backfill)
} catch let error {
self.log.error("Error trying to enable notifications on control characteristic: %{public}@", String(describing: error))
}
do {
try peripheral.stopListeningToCharacteristic(.authentication)
} catch let error {
self.log.error("Error trying to disable notifications on authentication characteristic: %{public}@", String(describing: error))
}
}
} else {
self.log.debug("Ignoring authentication response: %{public}@", response.hexadecimalString)
}
}
}


Expand Down Expand Up @@ -390,7 +412,7 @@ fileprivate extension PeripheralManager {
throw TransmitterError.authenticationError("Unable to parse auth status: \(error)")
}

guard challengeResponse.authenticated == 1 else {
guard challengeResponse.isAuthenticated else {
throw TransmitterError.authenticationError("Transmitter rejected auth challenge")
}

Expand Down Expand Up @@ -478,12 +500,19 @@ fileprivate extension PeripheralManager {
}
}

func listenToControl() throws {
func listenToCharacteristic(_ characteristic: CGMServiceCharacteristicUUID) throws {
do {
try setNotifyValue(true, for: .control)
try setNotifyValue(true, for: .backfill)
try setNotifyValue(true, for: characteristic)
} catch let error {
throw TransmitterError.controlError("Error enabling notification: \(error)")
throw TransmitterError.controlError("Error enabling notification for \(characteristic): \(error)")
}
}

func stopListeningToCharacteristic(_ characteristic: CGMServiceCharacteristicUUID) throws {
do {
try setNotifyValue(false, for: characteristic)
} catch let error {
throw TransmitterError.controlError("Error disabling notification for \(characteristic): \(error)")
}
}
}