From 01bda8b32f173622c438d59cb1665c0b16e73605 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 15 Jul 2019 00:27:37 -0500 Subject: [PATCH 1/3] Delay control subscription until after auth (#127) --- CGMBLEKit/BluetoothManager.swift | 11 ++++- CGMBLEKit/BluetoothServices.swift | 11 ++++- .../Messages/AuthChallengeRxMessage.swift | 8 ++-- CGMBLEKit/Transmitter.swift | 47 +++++++++++++++---- 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/CGMBLEKit/BluetoothManager.swift b/CGMBLEKit/BluetoothManager.swift index 2a0e50d2..a5622720 100644 --- a/CGMBLEKit/BluetoothManager.swift +++ b/CGMBLEKit/BluetoothManager.swift @@ -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) } @@ -318,12 +325,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) } } } diff --git a/CGMBLEKit/BluetoothServices.swift b/CGMBLEKit/BluetoothServices.swift index 4733bc77..85cce9cc 100644 --- a/CGMBLEKit/BluetoothServices.swift +++ b/CGMBLEKit/BluetoothServices.swift @@ -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" } diff --git a/CGMBLEKit/Messages/AuthChallengeRxMessage.swift b/CGMBLEKit/Messages/AuthChallengeRxMessage.swift index 5ebce938..40904d7f 100644 --- a/CGMBLEKit/Messages/AuthChallengeRxMessage.swift +++ b/CGMBLEKit/Messages/AuthChallengeRxMessage.swift @@ -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 { @@ -22,7 +22,7 @@ struct AuthChallengeRxMessage: TransmitterRxMessage { return nil } - authenticated = data[1] - bonded = data[2] + isAuthenticated = data[1] == 0x1 + isBonded = data[2] == 0x1 } } diff --git a/CGMBLEKit/Transmitter.swift b/CGMBLEKit/Transmitter.swift index 7c869b2b..b7473055 100644 --- a/CGMBLEKit/Transmitter.swift +++ b/CGMBLEKit/Transmitter.swift @@ -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) @@ -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() @@ -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) + } + } } @@ -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") } @@ -478,12 +500,19 @@ fileprivate extension PeripheralManager { } } - fileprivate 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)") } } } From 056a1352680d8eb06e28c35d722e097223e0ed59 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 15 Jul 2019 10:05:33 -0500 Subject: [PATCH 2/3] Bump LoopKit rev --- Cartfile.resolved | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index 24d76201..25696e33 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,2 +1,2 @@ -github "LoopKit/LoopKit" "v2.2.1" +github "LoopKit/LoopKit" "v2.2.2" github "LoopKit/dexcom-share-client-swift" "v1.0" From 3281ec9c7c49a4aeed00afa81a4e88ea8a410e0c Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 15 Jul 2019 10:06:30 -0500 Subject: [PATCH 3/3] Bump version --- CGMBLEKit Example/Info.plist | 2 +- CGMBLEKit.xcodeproj/project.pbxproj | 12 ++++++------ CGMBLEKit/Info.plist | 2 +- CGMBLEKitTests/Info.plist | 2 +- CGMBLEKitUI/Info.plist | 2 +- ResetTransmitter/Info.plist | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CGMBLEKit Example/Info.plist b/CGMBLEKit Example/Info.plist index e1919bb0..169d454f 100644 --- a/CGMBLEKit Example/Info.plist +++ b/CGMBLEKit Example/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 3.0 + 3.1 CFBundleVersion 1 LSRequiresIPhoneOS diff --git a/CGMBLEKit.xcodeproj/project.pbxproj b/CGMBLEKit.xcodeproj/project.pbxproj index 371727ca..4777cbd1 100644 --- a/CGMBLEKit.xcodeproj/project.pbxproj +++ b/CGMBLEKit.xcodeproj/project.pbxproj @@ -1302,7 +1302,7 @@ DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 20; + DYLIB_CURRENT_VERSION = 21; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1335,7 +1335,7 @@ DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 20; + DYLIB_CURRENT_VERSION = 21; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1387,7 +1387,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 20; + CURRENT_PROJECT_VERSION = 21; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -1457,7 +1457,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 20; + CURRENT_PROJECT_VERSION = 21; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -1496,7 +1496,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 20; + DYLIB_CURRENT_VERSION = 21; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -1523,7 +1523,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 20; + DYLIB_CURRENT_VERSION = 21; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/CGMBLEKit/Info.plist b/CGMBLEKit/Info.plist index 21baa19b..19c1e8d9 100644 --- a/CGMBLEKit/Info.plist +++ b/CGMBLEKit/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.0 + 3.1 CFBundleSignature ???? CFBundleVersion diff --git a/CGMBLEKitTests/Info.plist b/CGMBLEKitTests/Info.plist index fccbfa25..1c631839 100644 --- a/CGMBLEKitTests/Info.plist +++ b/CGMBLEKitTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 3.0 + 3.1 CFBundleSignature ???? CFBundleVersion diff --git a/CGMBLEKitUI/Info.plist b/CGMBLEKitUI/Info.plist index 7a3ea75e..a4e88d9d 100644 --- a/CGMBLEKitUI/Info.plist +++ b/CGMBLEKitUI/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.0 + 3.1 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/ResetTransmitter/Info.plist b/ResetTransmitter/Info.plist index dfee17af..e7e7b62e 100644 --- a/ResetTransmitter/Info.plist +++ b/ResetTransmitter/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 3.0 + 3.1 CFBundleVersion 1 LSRequiresIPhoneOS