diff --git a/.travis.yml b/.travis.yml index 4c1311b1..5134fb4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,16 @@ language: objective-c -osx_image: xcode7.3 -before_deploy: - - carthage build --no-skip-current +osx_image: xcode8 -cache: cocoapods -podfile: Example/Podfile +# cache: cocoapods +# podfile: Example/Podfile before_install: -- gem install cocoapods # Since Travis is not always on latest version -- pod install --project-directory=Example +# - gem install cocoapods # Since Travis is not always on latest version +# - pod install --project-directory=Example script: -- set -o pipefail && xcodebuild -workspace Example/xDripG5.xcworkspace -scheme xDripG5-Example -sdk iphonesimulator -destination name="iPhone 6" ONLY_ACTIVE_ARCH=NO | xcpretty -- xctool -project xDripG5.xcodeproj -scheme xDripG5 -sdk iphonesimulator9.3 build test -- pod lib lint +# Build cocoapods example project +# - set -o pipefail && xcodebuild -workspace Example/xDripG5.xcworkspace -scheme xDripG5-Example -sdk iphonesimulator -destination name="iPhone SE" ONLY_ACTIVE_ARCH=NO | xcpretty +# Build Travis project and run tests +- xcodebuild -project xDripG5.xcodeproj -scheme xDripG5 -sdk iphonesimulator10.0 build -destination name="iPhone SE" test +# - pod lib lint diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 9de38552..e87f3d63 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - xDripG5 (0.6.0) + - xDripG5 (0.7.0) DEPENDENCIES: - xDripG5 (from `../`) @@ -9,8 +9,8 @@ EXTERNAL SOURCES: :path: ../ SPEC CHECKSUMS: - xDripG5: ef0c18aa2916c968645fc20313e402b13eb5c845 + xDripG5: b0bfa28e1dc510799d919ab6a67badb56a024247 PODFILE CHECKSUM: 6b30cba971694d5258509315fb52eb645c9bc5e3 -COCOAPODS: 1.0.1 +COCOAPODS: 1.1.0.beta.2 diff --git a/Example/xDripG5.xcodeproj/project.pbxproj b/Example/xDripG5.xcodeproj/project.pbxproj index 3e3b7e86..be841e30 100644 --- a/Example/xDripG5.xcodeproj/project.pbxproj +++ b/Example/xDripG5.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 48; objects = { /* Begin PBXBuildFile section */ @@ -147,11 +147,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Nathan Racklyeft"; TargetAttributes = { 607FACCF1AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; + LastSwiftMigration = 0800; SystemCapabilities = { com.apple.BackgroundModes = { enabled = 1; @@ -161,7 +162,7 @@ }; }; buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "xDripG5" */; - compatibilityVersion = "Xcode 3.2"; + compatibilityVersion = "Xcode 8.0"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( @@ -204,7 +205,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; 2FC4228A9369221D367ED688 /* [CP] Copy Pods Resources */ = { @@ -286,8 +287,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -331,8 +334,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -351,6 +356,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -359,12 +365,14 @@ isa = XCBuildConfiguration; baseConfigurationReference = F3147B948B4F90A741304461 /* Pods-xDripG5_Example.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = xDripG5/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.xDripG5-Example"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -373,12 +381,14 @@ isa = XCBuildConfiguration; baseConfigurationReference = CFBD776BFE02F42998A8820B /* Pods-xDripG5_Example.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = xDripG5/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.xDripG5-Example"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/Example/xDripG5.xcodeproj/xcshareddata/xcschemes/xDripG5-Example.xcscheme b/Example/xDripG5.xcodeproj/xcshareddata/xcschemes/xDripG5-Example.xcscheme index a46d45e5..90e91734 100644 --- a/Example/xDripG5.xcodeproj/xcshareddata/xcschemes/xDripG5-Example.xcscheme +++ b/Example/xDripG5.xcodeproj/xcshareddata/xcschemes/xDripG5-Example.xcscheme @@ -1,6 +1,6 @@ Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { transmitter = Transmitter( - ID: NSUserDefaults.standardUserDefaults().transmitterID, - passiveModeEnabled: NSUserDefaults.standardUserDefaults().passiveModeEnabled + ID: UserDefaults.standard.transmitterID, + passiveModeEnabled: UserDefaults.standard.passiveModeEnabled ) - transmitter?.stayConnected = NSUserDefaults.standardUserDefaults().stayConnected + transmitter?.stayConnected = UserDefaults.standard.stayConnected transmitter?.delegate = self return true } - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - func applicationDidEnterBackground(application: UIApplication) { + func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. - if let transmitter = transmitter where !transmitter.stayConnected { + if let transmitter = transmitter , !transmitter.stayConnected { transmitter.stopScanning() } } - func applicationWillEnterForeground(application: UIApplication) { + func applicationWillEnterForeground(_ application: UIApplication) { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - func applicationDidBecomeActive(application: UIApplication) { + func applicationDidBecomeActive(_ application: UIApplication) { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. transmitter?.resumeScanning() } - func applicationWillTerminate(application: UIApplication) { + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } // MARK: - TransmitterDelegate - private let dateFormatter: NSDateFormatter = { - let dateFormatter = NSDateFormatter() + private let dateFormatter: DateFormatter = { + let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" - dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") + dateFormatter.locale = Locale(identifier: "en_US_POSIX") return dateFormatter }() - func transmitter(transmitter: Transmitter, didError error: ErrorType) { + func transmitter(_ transmitter: Transmitter, didError error: Error) { if let vc = window?.rootViewController as? TransmitterDelegate { - dispatch_async(dispatch_get_main_queue()) { + DispatchQueue.main.async { vc.transmitter(transmitter, didError: error) } } } - func transmitter(transmitter: Transmitter, didRead glucose: Glucose) { + func transmitter(_ transmitter: Transmitter, didRead glucose: Glucose) { if let vc = window?.rootViewController as? TransmitterDelegate { - dispatch_async(dispatch_get_main_queue()) { + DispatchQueue.main.async { vc.transmitter(transmitter, didRead: glucose) } } diff --git a/Example/xDripG5/Base.lproj/Main.storyboard b/Example/xDripG5/Base.lproj/Main.storyboard index e39acc7b..62b8b23b 100644 --- a/Example/xDripG5/Base.lproj/Main.storyboard +++ b/Example/xDripG5/Base.lproj/Main.storyboard @@ -1,9 +1,10 @@ - + - + + @@ -15,30 +16,25 @@ - + - - - - + - @@ -63,16 +59,13 @@ - - @@ -80,35 +73,28 @@ - - - - - + @@ -117,7 +103,7 @@ - + diff --git a/Example/xDripG5/NSUserDefaults.swift b/Example/xDripG5/NSUserDefaults.swift index 02fe0ec4..f9bd3a62 100644 --- a/Example/xDripG5/NSUserDefaults.swift +++ b/Example/xDripG5/NSUserDefaults.swift @@ -9,31 +9,31 @@ import Foundation -extension NSUserDefaults { +extension UserDefaults { var passiveModeEnabled: Bool { get { - return boolForKey("passiveModeEnabled") ?? false + return bool(forKey: "passiveModeEnabled") } set { - setBool(newValue, forKey: "passiveModeEnabled") + set(newValue, forKey: "passiveModeEnabled") } } var stayConnected: Bool { get { - return boolForKey("stayConnected") ?? true + return object(forKey: "stayConnected") != nil ? bool(forKey: "stayConnected") : true } set { - setBool(newValue, forKey: "stayConnected") + set(newValue, forKey: "stayConnected") } } var transmitterID: String { get { - return stringForKey("transmitterID") ?? "500000" + return string(forKey: "transmitterID") ?? "500000" } set { - setObject(newValue, forKey: "transmitterID") + set(newValue, forKey: "transmitterID") } } } diff --git a/Example/xDripG5/ViewController.swift b/Example/xDripG5/ViewController.swift index 5c882bf0..7cb49e21 100644 --- a/Example/xDripG5/ViewController.swift +++ b/Example/xDripG5/ViewController.swift @@ -27,14 +27,14 @@ class ViewController: UIViewController, TransmitterDelegate, UITextFieldDelegate override func viewDidLoad() { super.viewDidLoad() - passiveModeEnabledSwitch.on = AppDelegate.sharedDelegate.transmitter?.passiveModeEnabled ?? false + passiveModeEnabledSwitch.isOn = AppDelegate.sharedDelegate.transmitter?.passiveModeEnabled ?? false - stayConnectedSwitch.on = AppDelegate.sharedDelegate.transmitter?.stayConnected ?? false + stayConnectedSwitch.isOn = AppDelegate.sharedDelegate.transmitter?.stayConnected ?? false transmitterIDField.text = AppDelegate.sharedDelegate.transmitter?.ID } - override func viewDidAppear(animated: Bool) { + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) updateIndicatorViewDisplay() @@ -43,36 +43,36 @@ class ViewController: UIViewController, TransmitterDelegate, UITextFieldDelegate // MARK: - Actions func updateIndicatorViewDisplay() { - if let transmitter = AppDelegate.sharedDelegate.transmitter where transmitter.isScanning { + if let transmitter = AppDelegate.sharedDelegate.transmitter, transmitter.isScanning { scanningIndicatorView.startAnimating() } else { scanningIndicatorView.stopAnimating() } } - @IBAction func toggleStayConnected(sender: UISwitch) { - AppDelegate.sharedDelegate.transmitter?.stayConnected = sender.on - NSUserDefaults.standardUserDefaults().stayConnected = sender.on + @IBAction func toggleStayConnected(_ sender: UISwitch) { + AppDelegate.sharedDelegate.transmitter?.stayConnected = sender.isOn + UserDefaults.standard.stayConnected = sender.isOn updateIndicatorViewDisplay() } - @IBAction func togglePassiveMode(sender: UISwitch) { - AppDelegate.sharedDelegate.transmitter?.passiveModeEnabled = sender.on - NSUserDefaults.standardUserDefaults().passiveModeEnabled = sender.on + @IBAction func togglePassiveMode(_ sender: UISwitch) { + AppDelegate.sharedDelegate.transmitter?.passiveModeEnabled = sender.isOn + UserDefaults.standard.passiveModeEnabled = sender.isOn } // MARK: - UITextFieldDelegate - func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { if let text = textField.text { - let newString = text.stringByReplacingCharactersInRange(range.rangeOfString(text), withString: string) + let newString = text.replacingCharacters(in: range.rangeOfString(text), with: string) if newString.characters.count > 6 { return false } else if newString.characters.count == 6 { AppDelegate.sharedDelegate.transmitter?.ID = newString - NSUserDefaults.standardUserDefaults().transmitterID = newString + UserDefaults.standard.transmitterID = newString textField.text = newString @@ -85,47 +85,47 @@ class ViewController: UIViewController, TransmitterDelegate, UITextFieldDelegate return true } - func textFieldDidEndEditing(textField: UITextField) { + func textFieldDidEndEditing(_ textField: UITextField) { if textField.text?.characters.count != 6 { - textField.text = NSUserDefaults.standardUserDefaults().transmitterID + textField.text = UserDefaults.standard.transmitterID } } - func textFieldShouldEndEditing(textField: UITextField) -> Bool { + func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { return true } - func textFieldShouldReturn(textField: UITextField) -> Bool { + func textFieldShouldReturn(_ textField: UITextField) -> Bool { return true } // MARK: - TransmitterDelegate - func transmitter(transmitter: Transmitter, didError error: ErrorType) { + func transmitter(_ transmitter: Transmitter, didError error: Error) { titleLabel.text = NSLocalizedString("Error", comment: "Title displayed during error response") subtitleLabel.text = "\(error)" } - func transmitter(transmitter: Transmitter, didRead glucose: Glucose) { + func transmitter(_ transmitter: Transmitter, didRead glucose: Glucose) { let unit = HKUnit.milligramsPerDeciliter() - if let value = glucose.glucose?.doubleValueForUnit(unit) { + if let value = glucose.glucose?.doubleValue(for: unit) { titleLabel.text = "\(value) \(unit.unitString)" } else { - titleLabel.text = String(glucose.state) + titleLabel.text = String(describing: glucose.state) } let date = glucose.readDate - subtitleLabel.text = NSDateFormatter.localizedStringFromDate(date, dateStyle: .NoStyle, timeStyle: .LongStyle) + subtitleLabel.text = DateFormatter.localizedString(from: date, dateStyle: .none, timeStyle: .long) } } private extension NSRange { - func rangeOfString(string: String) -> Range { - let startIndex = string.startIndex.advancedBy(location) - let endIndex = startIndex.advancedBy(length) + func rangeOfString(_ string: String) -> Range { + let startIndex = string.characters.index(string.startIndex, offsetBy: location) + let endIndex = string.characters.index(startIndex, offsetBy: length) return startIndex.. Bool + func bluetoothManager(_ manager: BluetoothManager, shouldConnectPeripheral peripheral: CBPeripheral) -> Bool } -enum BluetoothManagerError: ErrorType { - case NotReady - case UnknownCharacteristic - case CBPeripheralError(NSError) - case Timeout +enum BluetoothManagerError: Error { + case notReady + case unknownCharacteristic + case cbPeripheralError(Error) + case timeout } private enum BluetoothOperationCondition { - case NotificationStateUpdate(characteristic: CBCharacteristic, enabled: Bool) - case ValueUpdate(characteristic: CBCharacteristic, firstByte: UInt8?) - case WriteUpdate(characteristic: CBCharacteristic) + case notificationStateUpdate(characteristic: CBCharacteristic, enabled: Bool) + case valueUpdate(characteristic: CBCharacteristic, firstByte: UInt8?) + case writeUpdate(characteristic: CBCharacteristic) } extension BluetoothOperationCondition: Hashable { var hashValue: Int { switch self { - case .NotificationStateUpdate(characteristic: let characteristic, enabled: let enabled): + case .notificationStateUpdate(characteristic: let characteristic, enabled: let enabled): return 1 ^ characteristic.hashValue ^ enabled.hashValue - case .ValueUpdate(characteristic: let characteristic, firstByte: let firstByte): + case .valueUpdate(characteristic: let characteristic, firstByte: let firstByte): return 2 ^ characteristic.hashValue ^ (firstByte?.hashValue ?? -1) - case .WriteUpdate(characteristic: let characteristic): + case .writeUpdate(characteristic: let characteristic): return 3 ^ characteristic.hashValue } } @@ -86,7 +86,7 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate // MARK: - GCD Management - private var managerQueue = dispatch_queue_create("com.loudnate.xDripG5.bluetoothManagerQueue", dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0)) + private var managerQueue = DispatchQueue(label: "com.loudnate.xDripG5.bluetoothManagerQueue", qos: .userInitiated) override init() { super.init() @@ -97,17 +97,17 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate // MARK: - Actions func scanForPeripheral() { - guard manager.state == .PoweredOn else { + guard manager.state == .poweredOn else { return } - if let peripheral = manager.retrieveConnectedPeripheralsWithServices([ + if let peripheral = manager.retrieveConnectedPeripherals(withServices: [ CBUUID(string: TransmitterServiceUUID.Advertisement.rawValue), CBUUID(string: TransmitterServiceUUID.CGMService.rawValue) - ]).first where delegate == nil || delegate!.bluetoothManager(self, shouldConnectPeripheral: peripheral) { + ]).first , delegate == nil || delegate!.bluetoothManager(self, shouldConnectPeripheral: peripheral) { self.peripheral = peripheral } else { - manager.scanForPeripheralsWithServices([ + manager.scanForPeripherals(withServices: [ CBUUID(string: TransmitterServiceUUID.Advertisement.rawValue) ], options: nil @@ -115,7 +115,7 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate } if let peripheral = self.peripheral { - self.manager.connectPeripheral(peripheral, options: nil) + self.manager.connect(peripheral, options: nil) } } @@ -135,9 +135,9 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate The sleep gives the transmitter time to shut down, but keeps the app running. */ - private func scanAfterDelay() { - dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)) { - NSThread.sleepForTimeInterval(2) + fileprivate func scanAfterDelay() { + DispatchQueue.global(qos: DispatchQoS.QoSClass.utility).async { + Thread.sleep(forTimeInterval: 2) self.scanForPeripheral() } @@ -157,23 +157,23 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate private var operationConditions: Set = [] /// Any error surfaced during the active operation - private var operationError: NSError? + private var operationError: Error? - func readValueForCharacteristicAndWait(UUID: CGMServiceCharacteristicUUID, timeout: NSTimeInterval = 2, expectingFirstByte firstByte: UInt8? = nil) throws -> NSData { - guard manager.state == .PoweredOn && operationConditions.isEmpty, let peripheral = peripheral else { - throw BluetoothManagerError.NotReady + func readValueForCharacteristicAndWait(_ UUID: CGMServiceCharacteristicUUID, timeout: TimeInterval = 2, expectingFirstByte firstByte: UInt8? = nil) throws -> Data { + guard manager.state == .poweredOn && operationConditions.isEmpty, let peripheral = peripheral else { + throw BluetoothManagerError.notReady } guard let characteristic = getCharacteristicWithUUID(UUID) else { - throw BluetoothManagerError.UnknownCharacteristic + throw BluetoothManagerError.unknownCharacteristic } operationLock.lock() - operationConditions.insert(.ValueUpdate(characteristic: characteristic, firstByte: firstByte)) + operationConditions.insert(.valueUpdate(characteristic: characteristic, firstByte: firstByte)) - peripheral.readValueForCharacteristic(characteristic) + peripheral.readValue(for: characteristic) - let signaled = operationLock.waitUntilDate(NSDate(timeIntervalSinceNow: timeout)) + let signaled = operationLock.wait(until: Date(timeIntervalSinceNow: timeout)) defer { operationConditions = [] @@ -182,29 +182,29 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate } if !signaled { - throw BluetoothManagerError.Timeout + throw BluetoothManagerError.timeout } else if let operationError = operationError { - throw BluetoothManagerError.CBPeripheralError(operationError) + throw BluetoothManagerError.cbPeripheralError(operationError) } - return characteristic.value ?? NSData() + return characteristic.value ?? Data() } - func setNotifyEnabledAndWait(enabled: Bool, forCharacteristicUUID UUID: CGMServiceCharacteristicUUID, timeout: NSTimeInterval = 2) throws { - guard manager.state == .PoweredOn && operationConditions.isEmpty, let peripheral = peripheral else { - throw BluetoothManagerError.NotReady + func setNotifyEnabledAndWait(_ enabled: Bool, forCharacteristicUUID UUID: CGMServiceCharacteristicUUID, timeout: TimeInterval = 2) throws { + guard manager.state == .poweredOn && operationConditions.isEmpty, let peripheral = peripheral else { + throw BluetoothManagerError.notReady } guard let characteristic = getCharacteristicWithUUID(UUID) else { - throw BluetoothManagerError.UnknownCharacteristic + throw BluetoothManagerError.unknownCharacteristic } operationLock.lock() - operationConditions.insert(.NotificationStateUpdate(characteristic: characteristic, enabled: enabled)) + operationConditions.insert(.notificationStateUpdate(characteristic: characteristic, enabled: enabled)) - peripheral.setNotifyValue(enabled, forCharacteristic: characteristic) + peripheral.setNotifyValue(enabled, for: characteristic) - let signaled = operationLock.waitUntilDate(NSDate(timeIntervalSinceNow: timeout)) + let signaled = operationLock.wait(until: Date(timeIntervalSinceNow: timeout)) defer { operationConditions = [] @@ -213,25 +213,25 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate } if !signaled { - throw BluetoothManagerError.Timeout + throw BluetoothManagerError.timeout } else if let operationError = operationError { - throw BluetoothManagerError.CBPeripheralError(operationError) + throw BluetoothManagerError.cbPeripheralError(operationError) } } - func waitForCharacteristicValueUpdate(UUID: CGMServiceCharacteristicUUID, timeout: NSTimeInterval = 5, expectingFirstByte firstByte: UInt8? = nil) throws -> NSData { - guard manager.state == .PoweredOn && operationConditions.isEmpty && peripheral != nil else { - throw BluetoothManagerError.NotReady + func waitForCharacteristicValueUpdate(_ UUID: CGMServiceCharacteristicUUID, timeout: TimeInterval = 5, expectingFirstByte firstByte: UInt8? = nil) throws -> Data { + guard manager.state == .poweredOn && operationConditions.isEmpty && peripheral != nil else { + throw BluetoothManagerError.notReady } - guard let characteristic = getCharacteristicWithUUID(UUID) where characteristic.isNotifying else { - throw BluetoothManagerError.UnknownCharacteristic + guard let characteristic = getCharacteristicWithUUID(UUID) , characteristic.isNotifying else { + throw BluetoothManagerError.unknownCharacteristic } operationLock.lock() - operationConditions.insert(.ValueUpdate(characteristic: characteristic, firstByte: firstByte)) + operationConditions.insert(.valueUpdate(characteristic: characteristic, firstByte: firstByte)) - let signaled = operationLock.waitUntilDate(NSDate(timeIntervalSinceNow: timeout)) + let signaled = operationLock.wait(until: Date(timeIntervalSinceNow: timeout)) defer { operationConditions = [] @@ -240,33 +240,33 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate } if !signaled { - throw BluetoothManagerError.Timeout + throw BluetoothManagerError.timeout } else if let operationError = operationError { - throw BluetoothManagerError.CBPeripheralError(operationError) + throw BluetoothManagerError.cbPeripheralError(operationError) } - return characteristic.value ?? NSData() + return characteristic.value ?? Data() } - func writeValueAndWait(value: NSData, forCharacteristicUUID UUID: CGMServiceCharacteristicUUID, timeout: NSTimeInterval = 2, expectingFirstByte firstByte: UInt8? = nil) throws -> NSData { - guard manager.state == .PoweredOn && operationConditions.isEmpty, let peripheral = peripheral else { - throw BluetoothManagerError.NotReady + func writeValueAndWait(_ value: Data, forCharacteristicUUID UUID: CGMServiceCharacteristicUUID, timeout: TimeInterval = 2, expectingFirstByte firstByte: UInt8? = nil) throws -> Data { + guard manager.state == .poweredOn && operationConditions.isEmpty, let peripheral = peripheral else { + throw BluetoothManagerError.notReady } guard let characteristic = getCharacteristicWithUUID(UUID) else { - throw BluetoothManagerError.UnknownCharacteristic + throw BluetoothManagerError.unknownCharacteristic } operationLock.lock() - operationConditions.insert(.WriteUpdate(characteristic: characteristic)) + operationConditions.insert(.writeUpdate(characteristic: characteristic)) if characteristic.isNotifying { - operationConditions.insert(.ValueUpdate(characteristic: characteristic, firstByte: firstByte)) + operationConditions.insert(.valueUpdate(characteristic: characteristic, firstByte: firstByte)) } - peripheral.writeValue(value, forCharacteristic: characteristic, type: .WithResponse) + peripheral.writeValue(value, for: characteristic, type: .withResponse) - let signaled = operationLock.waitUntilDate(NSDate(timeIntervalSinceNow: timeout)) + let signaled = operationLock.wait(until: Date(timeIntervalSinceNow: timeout)) defer { operationConditions = [] @@ -275,12 +275,12 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate } if !signaled { - throw BluetoothManagerError.Timeout + throw BluetoothManagerError.timeout } else if let operationError = operationError { - throw BluetoothManagerError.CBPeripheralError(operationError) + throw BluetoothManagerError.cbPeripheralError(operationError) } - return characteristic.value ?? NSData() + return characteristic.value ?? Data() } // MARK: - Accessors @@ -289,7 +289,7 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate return manager.isScanning } - private func getServiceWithUUID(UUID: TransmitterServiceUUID) -> CBService? { + private func getServiceWithUUID(_ UUID: TransmitterServiceUUID) -> CBService? { guard let services = peripheral?.services else { return nil } @@ -297,7 +297,7 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate return services.itemWithUUIDString(UUID.rawValue) } - private func getCharacteristicForServiceUUID(serviceUUID: TransmitterServiceUUID, withUUIDString UUIDString: String) -> CBCharacteristic? { + private func getCharacteristicForServiceUUID(_ serviceUUID: TransmitterServiceUUID, withUUIDString UUIDString: String) -> CBCharacteristic? { guard let characteristics = getServiceWithUUID(serviceUUID)?.characteristics else { return nil } @@ -305,26 +305,26 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate return characteristics.itemWithUUIDString(UUIDString) } - private func getCharacteristicWithUUID(UUID: CGMServiceCharacteristicUUID) -> CBCharacteristic? { + private func getCharacteristicWithUUID(_ UUID: CGMServiceCharacteristicUUID) -> CBCharacteristic? { return getCharacteristicForServiceUUID(.CGMService, withUUIDString: UUID.rawValue) } // MARK: - CBCentralManagerDelegate - func centralManagerDidUpdateState(central: CBCentralManager) { + func centralManagerDidUpdateState(_ central: CBCentralManager) { switch central.state { - case .PoweredOn: + case .poweredOn: if let peripheral = peripheral { - central.connectPeripheral(peripheral, options: nil) + central.connect(peripheral, options: nil) } else { scanForPeripheral() } - case .Resetting, .PoweredOff, .Unauthorized, .Unknown, .Unsupported: + case .resetting, .poweredOff, .unauthorized, .unknown, .unsupported: central.stopScan() } } - func centralManager(central: CBCentralManager, willRestoreState dict: [String : AnyObject]) { + func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) { if peripheral == nil, let peripherals = dict[CBCentralManagerRestoredStatePeripheralsKey] as? [CBPeripheral] { for peripheral in peripherals { if delegate == nil || delegate!.bluetoothManager(self, shouldConnectPeripheral: peripheral) { @@ -334,20 +334,20 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate } } - func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber) { + func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if delegate == nil || delegate!.bluetoothManager(self, shouldConnectPeripheral: peripheral) { self.peripheral = peripheral - central.connectPeripheral(peripheral, options: nil) + central.connect(peripheral, options: nil) central.stopScan() } } - func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) { + func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { central.stopScan() - let knownServiceUUIDs = peripheral.services?.flatMap({ $0.UUID }) ?? [] + let knownServiceUUIDs = peripheral.services?.flatMap({ $0.uuid }) ?? [] let servicesToDiscover = [ CBUUID(string: TransmitterServiceUUID.CGMService.rawValue) @@ -360,13 +360,13 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate } } - func centralManager(central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) { + func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { if stayConnected { scanAfterDelay() } } - func centralManager(central: CBCentralManager, didFailToConnectPeripheral peripheral: CBPeripheral, error: NSError?) { + func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { if stayConnected { scanAfterDelay() } @@ -374,12 +374,12 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate // MARK: - CBPeripheralDelegate - func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) { - for service in peripheral.services ?? [] where service.UUID.UUIDString == TransmitterServiceUUID.CGMService.rawValue { + func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { + for service in peripheral.services ?? [] where service.uuid.uuidString == TransmitterServiceUUID.CGMService.rawValue { var characteristicsToDiscover = [CBUUID]() - let knownCharacteristics = service.characteristics?.flatMap({ $0.UUID }) ?? [] + let knownCharacteristics = service.characteristics?.flatMap({ $0.uuid }) ?? [] - switch TransmitterServiceUUID(rawValue: service.UUID.UUIDString) { + switch TransmitterServiceUUID(rawValue: service.uuid.uuidString) { case .CGMService?: characteristicsToDiscover = [ CBUUID(string: CGMServiceCharacteristicUUID.Communication.rawValue), @@ -395,22 +395,22 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate characteristicsToDiscover = characteristicsToDiscover.filter({ !knownCharacteristics.contains($0) }) if characteristicsToDiscover.count > 0 { - peripheral.discoverCharacteristics(characteristicsToDiscover, forService: service) + peripheral.discoverCharacteristics(characteristicsToDiscover, for: service) } else { - self.peripheral(peripheral, didDiscoverCharacteristicsForService: service, error: nil) + self.peripheral(peripheral, didDiscoverCharacteristicsFor: service, error: nil) } } } - func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) { + func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { self.delegate?.bluetoothManager(self, isReadyWithError: error) } - func peripheral(peripheral: CBPeripheral, didUpdateNotificationStateForCharacteristic characteristic: CBCharacteristic, error: NSError?) { + func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) { operationLock.lock() - if operationConditions.remove(.NotificationStateUpdate(characteristic: characteristic, enabled: characteristic.isNotifying)) != nil { + if operationConditions.remove(.notificationStateUpdate(characteristic: characteristic, enabled: characteristic.isNotifying)) != nil { operationError = error if operationConditions.isEmpty { @@ -421,12 +421,12 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate operationLock.unlock() } - func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) { + func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { operationLock.lock() - if operationConditions.remove(.ValueUpdate(characteristic: characteristic, firstByte: characteristic.value?[0])) != nil || - operationConditions.remove(.ValueUpdate(characteristic: characteristic, firstByte: nil)) != nil + if operationConditions.remove(.valueUpdate(characteristic: characteristic, firstByte: characteristic.value?[0])) != nil || + operationConditions.remove(.valueUpdate(characteristic: characteristic, firstByte: nil)) != nil { operationError = error @@ -438,11 +438,11 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate operationLock.unlock() } - func peripheral(peripheral: CBPeripheral, didWriteValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) { + func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { self.operationLock.lock() - if operationConditions.remove(.WriteUpdate(characteristic: characteristic)) != nil { + if operationConditions.remove(.writeUpdate(characteristic: characteristic)) != nil { operationError = error if operationConditions.isEmpty { @@ -457,9 +457,9 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate private extension Array where Element: CBAttribute { - func itemWithUUIDString(UUIDString: String) -> Element? { + func itemWithUUIDString(_ UUIDString: String) -> Element? { for attribute in self { - if attribute.UUID.UUIDString == UUIDString { + if attribute.uuid.uuidString == UUIDString { return attribute } } diff --git a/xDripG5/CalibrationState.swift b/xDripG5/CalibrationState.swift index 60534f68..f27c3250 100644 --- a/xDripG5/CalibrationState.swift +++ b/xDripG5/CalibrationState.swift @@ -12,35 +12,35 @@ import Foundation public enum CalibrationState { public typealias RawValue = UInt8 - case Stopped - case Warmup - case NeedFirstInitialCalibration - case NeedSecondInitialCalibration - case OK - case NeedCalibration - case Unknown(RawValue) + case stopped + case warmup + case needFirstInitialCalibration + case needSecondInitialCalibration + case ok + case needCalibration + case unknown(RawValue) init(rawValue: UInt8) { switch rawValue { case 1: - self = .Stopped + self = .stopped case 2: - self = .Warmup + self = .warmup case 4: - self = .NeedFirstInitialCalibration + self = .needFirstInitialCalibration case 5: - self = .NeedSecondInitialCalibration + self = .needSecondInitialCalibration case 6: - self = .OK + self = .ok case 7: - self = .NeedCalibration + self = .needCalibration default: - self = .Unknown(rawValue) + self = .unknown(rawValue) } } public var hasReliableGlucose: Bool { - return self == .OK || self == .NeedCalibration + return self == .ok || self == .needCalibration } } @@ -48,9 +48,9 @@ extension CalibrationState: Equatable { } public func ==(lhs: CalibrationState, rhs: CalibrationState) -> Bool { switch (lhs, rhs) { - case (.Stopped, .Stopped), (.Warmup, .Warmup), (.NeedFirstInitialCalibration, .NeedFirstInitialCalibration), (.NeedSecondInitialCalibration, .NeedSecondInitialCalibration), (.OK, .OK), (.NeedCalibration, .NeedCalibration): + case (.stopped, .stopped), (.warmup, .warmup), (.needFirstInitialCalibration, .needFirstInitialCalibration), (.needSecondInitialCalibration, .needSecondInitialCalibration), (.ok, .ok), (.needCalibration, .needCalibration): return true - case let (.Unknown(lhsRaw), .Unknown(rhsRaw)): + case let (.unknown(lhsRaw), .unknown(rhsRaw)): return lhsRaw == rhsRaw default: return false diff --git a/xDripG5/Glucose.swift b/xDripG5/Glucose.swift index 773d0632..a4a50e64 100644 --- a/xDripG5/Glucose.swift +++ b/xDripG5/Glucose.swift @@ -14,23 +14,23 @@ public struct Glucose { public let glucoseMessage: GlucoseRxMessage let timeMessage: TransmitterTimeRxMessage - init(glucoseMessage: GlucoseRxMessage, timeMessage: TransmitterTimeRxMessage, activationDate: NSDate) { + init(glucoseMessage: GlucoseRxMessage, timeMessage: TransmitterTimeRxMessage, activationDate: Date) { self.glucoseMessage = glucoseMessage self.timeMessage = timeMessage status = TransmitterStatus(rawValue: glucoseMessage.status) state = CalibrationState(rawValue: glucoseMessage.state) - sessionStartDate = activationDate.dateByAddingTimeInterval(NSTimeInterval(timeMessage.sessionStartTime)) - readDate = activationDate.dateByAddingTimeInterval(NSTimeInterval(glucoseMessage.timestamp)) + sessionStartDate = activationDate.addingTimeInterval(TimeInterval(timeMessage.sessionStartTime)) + readDate = activationDate.addingTimeInterval(TimeInterval(glucoseMessage.timestamp)) } // MARK: - Transmitter Info public let status: TransmitterStatus - public let sessionStartDate: NSDate + public let sessionStartDate: Date // MARK: - Glucose Info public let state: CalibrationState - public let readDate: NSDate + public let readDate: Date public var isDisplayOnly: Bool { return glucoseMessage.glucoseIsDisplayOnly diff --git a/xDripG5/HKUnit.swift b/xDripG5/HKUnit.swift index edd297b8..34196bf7 100644 --- a/xDripG5/HKUnit.swift +++ b/xDripG5/HKUnit.swift @@ -11,6 +11,6 @@ import HealthKit extension HKUnit { static func milligramsPerDeciliter() -> HKUnit { - return HKUnit.gramUnitWithMetricPrefix(.Milli).unitDividedByUnit(HKUnit.literUnitWithMetricPrefix(.Deci)) + return HKUnit.gramUnit(with: .milli).unitDivided(by: HKUnit.literUnit(with: .deci)) } } diff --git a/xDripG5/Info.plist b/xDripG5/Info.plist index 63c3e67d..3157e479 100644 --- a/xDripG5/Info.plist +++ b/xDripG5/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.6.0 + 0.7.0 CFBundleSignature ???? CFBundleVersion diff --git a/xDripG5/Messages/AuthChallengeRxMessage.swift b/xDripG5/Messages/AuthChallengeRxMessage.swift index 5fd4a77c..90e00643 100644 --- a/xDripG5/Messages/AuthChallengeRxMessage.swift +++ b/xDripG5/Messages/AuthChallengeRxMessage.swift @@ -11,19 +11,19 @@ import Foundation struct AuthChallengeRxMessage: TransmitterRxMessage { static let opcode: UInt8 = 0x3 - let tokenHash: NSData - let challenge: NSData + let tokenHash: Data + let challenge: Data - init?(data: NSData) { - if data.length >= 17 { - if data[0] == self.dynamicType.opcode { - tokenHash = data[1..<9] - challenge = data[9..<17] - } else { - return nil - } - } else { + init?(data: Data) { + guard data.count >= 17 else { return nil } + + guard data[0] == type(of: self).opcode else { + return nil + } + + tokenHash = data.subdata(in: 1..<9) + challenge = data.subdata(in: 9..<17) } -} \ No newline at end of file +} diff --git a/xDripG5/Messages/AuthChallengeTxMessage.swift b/xDripG5/Messages/AuthChallengeTxMessage.swift index 731fa59b..1143f16f 100644 --- a/xDripG5/Messages/AuthChallengeTxMessage.swift +++ b/xDripG5/Messages/AuthChallengeTxMessage.swift @@ -11,7 +11,7 @@ import Foundation struct AuthChallengeTxMessage: TransmitterTxMessage { let opcode: UInt8 = 0x4 - let challengeHash: NSData + let challengeHash: Data var byteSequence: [Any] { return [opcode, challengeHash] diff --git a/xDripG5/Messages/AuthRequestTxMessage.swift b/xDripG5/Messages/AuthRequestTxMessage.swift index be007bf1..8b27c5c5 100644 --- a/xDripG5/Messages/AuthRequestTxMessage.swift +++ b/xDripG5/Messages/AuthRequestTxMessage.swift @@ -11,15 +11,15 @@ import Foundation struct AuthRequestTxMessage: TransmitterTxMessage { let opcode: UInt8 = 0x1 - let singleUseToken: NSData + let singleUseToken: Data let endByte: UInt8 = 0x2 init() { - var UUIDBytes = [UInt8](count: 16, repeatedValue: 0) + var UUIDBytes = [UInt8](repeating: 0, count: 16) - NSUUID().getUUIDBytes(&UUIDBytes) + NSUUID().getBytes(&UUIDBytes) - singleUseToken = NSData(bytes: &UUIDBytes, length: 8) + singleUseToken = Data(bytes: UUIDBytes) } var byteSequence: [Any] { diff --git a/xDripG5/Messages/AuthStatusRxMessage.swift b/xDripG5/Messages/AuthStatusRxMessage.swift index 23962e7f..473bd158 100644 --- a/xDripG5/Messages/AuthStatusRxMessage.swift +++ b/xDripG5/Messages/AuthStatusRxMessage.swift @@ -14,16 +14,16 @@ struct AuthStatusRxMessage: TransmitterRxMessage { let authenticated: UInt8 let bonded: UInt8 - init?(data: NSData) { - if data.length >= 3 { - if data[0] == self.dynamicType.opcode { - self.authenticated = data[1] - self.bonded = data[2] - } else { - return nil - } - } else { + init?(data: Data) { + guard data.count >= 3 else { return nil } + + guard data[0] == type(of: self).opcode else { + return nil + } + + authenticated = data[1] + bonded = data[2] } } diff --git a/xDripG5/Messages/GlucoseRxMessage.swift b/xDripG5/Messages/GlucoseRxMessage.swift index e1d290ea..1c6b9d87 100644 --- a/xDripG5/Messages/GlucoseRxMessage.swift +++ b/xDripG5/Messages/GlucoseRxMessage.swift @@ -19,25 +19,25 @@ public struct GlucoseRxMessage: TransmitterRxMessage { public let state: UInt8 public let trend: Int8 - init?(data: NSData) { - if data.length == 16 && data.crcValid() { - if data[0] == self.dynamicType.opcode { - status = data[1] - sequence = data[2...5] - timestamp = data[6...9] - - let glucoseBytes: UInt16 = data[10...11] - glucoseIsDisplayOnly = (glucoseBytes & 0xf000) > 0 - glucose = glucoseBytes & 0xfff - - state = data[12] - trend = data[13] - } else { - return nil - } - } else { + init?(data: Data) { + guard data.count == 16 && data.crcValid() else { return nil } + + guard data[0] == type(of: self).opcode else { + return nil + } + + status = data[1] + sequence = data[2..<6] + timestamp = data[6..<10] + + let glucoseBytes: UInt16 = data[10..<12] + glucoseIsDisplayOnly = (glucoseBytes & 0xf000) > 0 + glucose = glucoseBytes & 0xfff + + state = data[12] + trend = Int8(bitPattern: data[13]) } } diff --git a/xDripG5/Messages/SessionStartRxMessage.swift b/xDripG5/Messages/SessionStartRxMessage.swift index cc230cc9..0ea5e0aa 100644 --- a/xDripG5/Messages/SessionStartRxMessage.swift +++ b/xDripG5/Messages/SessionStartRxMessage.swift @@ -20,19 +20,19 @@ struct SessionStartRxMessage { let transmitterTime: UInt32 - init?(data: NSData) { - guard data.length == 17 && data.crcValid() else { + init?(data: Data) { + guard data.count == 17 && data.crcValid() else { return nil } - guard data[0] == self.dynamicType.opcode else { + guard data[0] == type(of: self).opcode else { return nil } status = data[1] received = data[2] - requestedStartTime = data[3...6] - sessionStartTime = data[7...10] - transmitterTime = data[11...14] + requestedStartTime = data[3..<7] + sessionStartTime = data[7..<11] + transmitterTime = data[11..<15] } } diff --git a/xDripG5/Messages/SessionStopRxMessage.swift b/xDripG5/Messages/SessionStopRxMessage.swift index 8978eac5..e05fadd3 100644 --- a/xDripG5/Messages/SessionStopRxMessage.swift +++ b/xDripG5/Messages/SessionStopRxMessage.swift @@ -17,19 +17,19 @@ struct SessionStopRxMessage { let sessionStartTime: UInt32 let transmitterTime: UInt32 - init?(data: NSData) { - guard data.length == 17 && data.crcValid() else { + init?(data: Data) { + guard data.count == 17 && data.crcValid() else { return nil } - guard data[0] == self.dynamicType.opcode else { + guard data[0] == type(of: self).opcode else { return nil } status = data[1] received = data[2] - sessionStopTime = data[3...6] - sessionStartTime = data[7...10] - transmitterTime = data[11...14] + sessionStopTime = data[3..<7] + sessionStartTime = data[7..<11] + transmitterTime = data[11..<15] } } diff --git a/xDripG5/Messages/TransmitterMessage.swift b/xDripG5/Messages/TransmitterMessage.swift index 5c2a08c2..340b8a45 100644 --- a/xDripG5/Messages/TransmitterMessage.swift +++ b/xDripG5/Messages/TransmitterMessage.swift @@ -13,13 +13,13 @@ protocol TransmitterTxMessage { var byteSequence: [Any] { get } - var data: NSData { get } + var data: Data { get } } extension TransmitterTxMessage { - var data: NSData { + var data: Data { let data = NSMutableData() for item in byteSequence { @@ -27,33 +27,33 @@ extension TransmitterTxMessage { case let i as Int8: var value = i - data.appendBytes(&value, length: 1) + data.append(&value, length: 1) case let i as UInt8: var value = i - data.appendBytes(&value, length: 1) + data.append(&value, length: 1) case let i as UInt16: var value = i - data.appendBytes(&value, length: 2) + data.append(&value, length: 2) case let i as UInt32: var value = i - data.appendBytes(&value, length: 4) - case let i as NSData: - data.appendData(i) + data.append(&value, length: 4) + case let i as Data: + data.append(i) default: fatalError("\(item) not supported") } } - return data + return data as Data } } protocol TransmitterRxMessage { - init?(data: NSData) + init?(data: Data) -} \ No newline at end of file +} diff --git a/xDripG5/Messages/TransmitterTimeRxMessage.swift b/xDripG5/Messages/TransmitterTimeRxMessage.swift index a2bc7b71..8c95a312 100644 --- a/xDripG5/Messages/TransmitterTimeRxMessage.swift +++ b/xDripG5/Messages/TransmitterTimeRxMessage.swift @@ -15,18 +15,18 @@ struct TransmitterTimeRxMessage: TransmitterRxMessage { let currentTime: UInt32 let sessionStartTime: UInt32 - init?(data: NSData) { - guard data.length == 16 && data.crcValid() else { + init?(data: Data) { + guard data.count == 16 && data.crcValid() else { return nil } - guard data[0] == self.dynamicType.opcode else { + guard data[0] == type(of: self).opcode else { return nil } status = data[1] - currentTime = data[2...5] - sessionStartTime = data[6...9] + currentTime = data[2..<6] + sessionStartTime = data[6..<10] } } diff --git a/xDripG5/NSData+CRC.swift b/xDripG5/NSData+CRC.swift index 128ee53b..5bf33cac 100644 --- a/xDripG5/NSData+CRC.swift +++ b/xDripG5/NSData+CRC.swift @@ -16,12 +16,10 @@ import Foundation [http://web.mit.edu/6.115/www/amulet/xmodem.htm]() */ -func CRCCCITTXModem(bytes: [UInt8], count: Int? = nil) -> UInt16 { - let count = count ?? bytes.count - +private func CRCCCITTXModem(_ bytes: Data) -> UInt16 { var crc: UInt16 = 0 - for byte in bytes[0.. UInt16 { extension UInt8 { func crc16() -> UInt16 { - return CRCCCITTXModem([self]) + return CRCCCITTXModem(Data(bytes: [self])) } } -extension NSData { +extension Data { func crc16() -> UInt16 { - return CRCCCITTXModem(self[0.. Bool { - return CRCCCITTXModem(self[0.. Int8 { +public extension Data { + /*@nonobjc subscript(index: Int) -> Int8 { let bytes: [Int8] = self[index...index] return bytes[0] @@ -21,44 +21,52 @@ public extension NSData { return bytes[0] } - +*/ @nonobjc subscript(range: Range) -> UInt16 { - return self[range][0] + var dataArray: UInt16 = 0 + let buffer = UnsafeMutableBufferPointer(start: &dataArray, count: range.count) + _ = self.copyBytes(to: buffer, from: range) + + return dataArray } @nonobjc subscript(range: Range) -> UInt32 { - return self[range][0] - } + var dataArray: UInt32 = 0 + let buffer = UnsafeMutableBufferPointer(start: &dataArray, count: range.count) + _ = self.copyBytes(to: buffer, from: range) + return dataArray + } +/* subscript(range: Range) -> [Int8] { - var dataArray = [Int8](count: range.count, repeatedValue: 0) - self.getBytes(&dataArray, range: NSRange(range)) + var dataArray = [Int8](repeating: 0, count: range.count) + let buffer = UnsafeMutableBufferPointer(start: &dataArray, count: range.count) + _ = self.copyBytes(to: buffer, from: range) return dataArray } subscript(range: Range) -> [UInt8] { - var dataArray = [UInt8](count: range.count, repeatedValue: 0) - self.getBytes(&dataArray, range: NSRange(range)) + var dataArray = [UInt8](repeating: 0, count: range.count) + self.copyBytes(to: &dataArray, from: range) return dataArray } subscript(range: Range) -> [UInt16] { - var dataArray = [UInt16](count: range.count / 2, repeatedValue: 0) - self.getBytes(&dataArray, range: NSRange(range)) + var dataArray = [UInt16](repeating: 0, count: range.count / 2) + let buffer = UnsafeMutableBufferPointer(start: &dataArray, count: range.count) + _ = self.copyBytes(to: buffer, from: range) return dataArray } subscript(range: Range) -> [UInt32] { - var dataArray = [UInt32](count: range.count / 4, repeatedValue: 0) - self.getBytes(&dataArray, range: NSRange(range)) + var dataArray = [UInt32](repeating: 0, count: range.count / 4) + let buffer = UnsafeMutableBufferPointer(start: &dataArray, count: range.count) + _ = self.copyBytes(to: buffer, from: range) return dataArray } - - subscript(range: Range) -> NSData { - return subdataWithRange(NSRange(range)) - } + */ } diff --git a/xDripG5/Transmitter.swift b/xDripG5/Transmitter.swift index 9f2c2864..e222ceba 100644 --- a/xDripG5/Transmitter.swift +++ b/xDripG5/Transmitter.swift @@ -11,25 +11,25 @@ import CoreBluetooth public protocol TransmitterDelegate: class { - func transmitter(transmitter: Transmitter, didError error: ErrorType) + func transmitter(_ transmitter: Transmitter, didError error: Error) - func transmitter(transmitter: Transmitter, didRead glucose: Glucose) + func transmitter(_ transmitter: Transmitter, didRead glucose: Glucose) } -public enum TransmitterError: ErrorType { - case AuthenticationError(String) - case ControlError(String) +public enum TransmitterError: Error { + case authenticationError(String) + case controlError(String) } -public class Transmitter: BluetoothManagerDelegate { +public final class Transmitter: BluetoothManagerDelegate { /// The ID of the transmitter to connect to public var ID: String /// The initial activation date of the transmitter - public private(set) var activationDate: NSDate? + public private(set) var activationDate: Date? public var passiveModeEnabled: Bool @@ -37,7 +37,7 @@ public class Transmitter: BluetoothManagerDelegate { private let bluetoothManager = BluetoothManager() - private var operationQueue = dispatch_queue_create("com.loudnate.xDripG5.transmitterOperationQueue", DISPATCH_QUEUE_SERIAL) + private var operationQueue = DispatchQueue(label: "com.loudnate.xDripG5.transmitterOperationQueue") public init(ID: String, passiveModeEnabled: Bool = false) { self.ID = ID @@ -75,13 +75,13 @@ public class Transmitter: BluetoothManagerDelegate { // MARK: - BluetoothManagerDelegate - func bluetoothManager(manager: BluetoothManager, isReadyWithError error: NSError?) { + func bluetoothManager(_ manager: BluetoothManager, isReadyWithError error: Error?) { if let error = error { self.delegate?.transmitter(self, didError: error) return } - dispatch_async(operationQueue) { + operationQueue.async { if self.passiveModeEnabled { do { try self.listenToControl() @@ -111,12 +111,12 @@ public class Transmitter: BluetoothManagerDelegate { - returns: A new string, containing the last two characters of the input string */ - private func lastTwoCharactersOfString(string: String) -> String { - return string.substringFromIndex(string.endIndex.advancedBy(-2, limit: string.startIndex)) + private func lastTwoCharactersOfString(_ string: String) -> String { + return string.substring(from: string.characters.index(string.endIndex, offsetBy: -2, limitedBy: string.startIndex)!) } - func bluetoothManager(manager: BluetoothManager, shouldConnectPeripheral peripheral: CBPeripheral) -> Bool { - if let name = peripheral.name where lastTwoCharactersOfString(name) == lastTwoCharactersOfString(ID) { + func bluetoothManager(_ manager: BluetoothManager, shouldConnectPeripheral peripheral: CBPeripheral) -> Bool { + if let name = peripheral.name , lastTwoCharactersOfString(name) == lastTwoCharactersOfString(ID) { return true } else { return false @@ -126,71 +126,71 @@ public class Transmitter: BluetoothManagerDelegate { // MARK: - Helpers private func authenticate() throws { - if let data = try? bluetoothManager.readValueForCharacteristicAndWait(.Authentication), - status = AuthStatusRxMessage(data: data) where status.authenticated == 1 && status.bonded == 1 + if let data = try? bluetoothManager.readValueForCharacteristicAndWait(.Authentication), + let status = AuthStatusRxMessage(data: data), status.authenticated == 1 && status.bonded == 1 { NSLog("Transmitter already authenticated.") } else { do { try bluetoothManager.setNotifyEnabledAndWait(true, forCharacteristicUUID: .Authentication) } catch let error { - throw TransmitterError.AuthenticationError("Error enabling notification: \(error)") + throw TransmitterError.authenticationError("Error enabling notification: \(error)") } let authMessage = AuthRequestTxMessage() - let data: NSData + let data: Data do { data = try bluetoothManager.writeValueAndWait(authMessage.data, forCharacteristicUUID: .Authentication, expectingFirstByte: AuthChallengeRxMessage.opcode) } catch let error { - throw TransmitterError.AuthenticationError("Error writing transmitter challenge: \(error)") + throw TransmitterError.authenticationError("Error writing transmitter challenge: \(error)") } guard let response = AuthChallengeRxMessage(data: data) else { - throw TransmitterError.AuthenticationError("Unable to parse auth challenge: \(data)") + throw TransmitterError.authenticationError("Unable to parse auth challenge: \(data)") } guard response.tokenHash == self.calculateHash(authMessage.singleUseToken) else { - throw TransmitterError.AuthenticationError("Transmitter failed auth challenge") + throw TransmitterError.authenticationError("Transmitter failed auth challenge") } if let challengeHash = self.calculateHash(response.challenge) { - let data: NSData + let data: Data do { data = try bluetoothManager.writeValueAndWait(AuthChallengeTxMessage(challengeHash: challengeHash).data, forCharacteristicUUID: .Authentication, expectingFirstByte: AuthStatusRxMessage.opcode) } catch let error { - throw TransmitterError.AuthenticationError("Error writing challenge response: \(error)") + throw TransmitterError.authenticationError("Error writing challenge response: \(error)") } guard let response = AuthStatusRxMessage(data: data) else { - throw TransmitterError.AuthenticationError("Unable to parse auth status: \(data)") + throw TransmitterError.authenticationError("Unable to parse auth status: \(data)") } guard response.authenticated == 1 else { - throw TransmitterError.AuthenticationError("Transmitter rejected auth challenge") + throw TransmitterError.authenticationError("Transmitter rejected auth challenge") } if response.bonded != 0x1 { do { - try bluetoothManager.writeValueAndWait(KeepAliveTxMessage(time: 25).data, forCharacteristicUUID: .Authentication) + _ = try bluetoothManager.writeValueAndWait(KeepAliveTxMessage(time: 25).data, forCharacteristicUUID: .Authentication) } catch let error { - throw TransmitterError.AuthenticationError("Error writing keep-alive for bond: \(error)") + throw TransmitterError.authenticationError("Error writing keep-alive for bond: \(error)") } - let data: NSData + let data: Data do { // Wait for the OS dialog to pop-up before continuing. data = try bluetoothManager.writeValueAndWait(BondRequestTxMessage().data, forCharacteristicUUID: .Authentication, timeout: 15, expectingFirstByte: AuthStatusRxMessage.opcode) } catch let error { - throw TransmitterError.AuthenticationError("Error writing bond request: \(error)") + throw TransmitterError.authenticationError("Error writing bond request: \(error)") } guard let response = AuthStatusRxMessage(data: data) else { - throw TransmitterError.AuthenticationError("Unable to parse auth status: \(data)") + throw TransmitterError.authenticationError("Unable to parse auth status: \(data)") } guard response.bonded == 0x1 else { - throw TransmitterError.AuthenticationError("Transmitter failed to bond") + throw TransmitterError.authenticationError("Transmitter failed to bond") } } } @@ -198,7 +198,7 @@ public class Transmitter: BluetoothManagerDelegate { do { try bluetoothManager.setNotifyEnabledAndWait(false, forCharacteristicUUID: .Authentication) } catch let error { - throw TransmitterError.AuthenticationError("Error disabling notification: \(error)") + throw TransmitterError.authenticationError("Error disabling notification: \(error)") } } } @@ -207,31 +207,31 @@ public class Transmitter: BluetoothManagerDelegate { do { try bluetoothManager.setNotifyEnabledAndWait(true, forCharacteristicUUID: .Control) } catch let error { - throw TransmitterError.ControlError("Error enabling notification: \(error)") + throw TransmitterError.controlError("Error enabling notification: \(error)") } - let timeData: NSData + let timeData: Data do { timeData = try bluetoothManager.writeValueAndWait(TransmitterTimeTxMessage().data, forCharacteristicUUID: .Control, expectingFirstByte: TransmitterTimeRxMessage.opcode) } catch let error { - throw TransmitterError.ControlError("Error writing time request: \(error)") + throw TransmitterError.controlError("Error writing time request: \(error)") } guard let timeMessage = TransmitterTimeRxMessage(data: timeData) else { - throw TransmitterError.ControlError("Unable to parse time response: \(timeData)") + throw TransmitterError.controlError("Unable to parse time response: \(timeData)") } - let activationDate = NSDate(timeIntervalSinceNow: -NSTimeInterval(timeMessage.currentTime)) + let activationDate = Date(timeIntervalSinceNow: -TimeInterval(timeMessage.currentTime)) - let glucoseData: NSData + let glucoseData: Data do { glucoseData = try bluetoothManager.writeValueAndWait(GlucoseTxMessage().data, forCharacteristicUUID: .Control, expectingFirstByte: GlucoseRxMessage.opcode) } catch let error { - throw TransmitterError.ControlError("Error writing glucose request: \(error)") + throw TransmitterError.controlError("Error writing glucose request: \(error)") } guard let glucoseMessage = GlucoseRxMessage(data: glucoseData) else { - throw TransmitterError.ControlError("Unable to parse glucose response: \(glucoseData)") + throw TransmitterError.controlError("Unable to parse glucose response: \(glucoseData)") } // Update and notify @@ -240,7 +240,7 @@ public class Transmitter: BluetoothManagerDelegate { do { try bluetoothManager.setNotifyEnabledAndWait(false, forCharacteristicUUID: .Control) - try bluetoothManager.writeValueAndWait(DisconnectTxMessage().data, forCharacteristicUUID: .Control) + _ = try bluetoothManager.writeValueAndWait(DisconnectTxMessage().data, forCharacteristicUUID: .Control) } catch { } } @@ -249,31 +249,31 @@ public class Transmitter: BluetoothManagerDelegate { do { try bluetoothManager.setNotifyEnabledAndWait(true, forCharacteristicUUID: .Control) } catch let error { - throw TransmitterError.ControlError("Error enabling notification: \(error)") + throw TransmitterError.controlError("Error enabling notification: \(error)") } - let timeData: NSData + let timeData: Data do { timeData = try bluetoothManager.waitForCharacteristicValueUpdate(.Control, expectingFirstByte: TransmitterTimeRxMessage.opcode) } catch let error { - throw TransmitterError.ControlError("Error waiting for time response: \(error)") + throw TransmitterError.controlError("Error waiting for time response: \(error)") } guard let timeMessage = TransmitterTimeRxMessage(data: timeData) else { - throw TransmitterError.ControlError("Unable to parse time response: \(timeData)") + throw TransmitterError.controlError("Unable to parse time response: \(timeData)") } - let activationDate = NSDate(timeIntervalSinceNow: -NSTimeInterval(timeMessage.currentTime)) + let activationDate = Date(timeIntervalSinceNow: -TimeInterval(timeMessage.currentTime)) - let glucoseData: NSData + let glucoseData: Data do { glucoseData = try bluetoothManager.waitForCharacteristicValueUpdate(.Control, expectingFirstByte: GlucoseRxMessage.opcode) } catch let error { - throw TransmitterError.ControlError("Error waiting for glucose response: \(error)") + throw TransmitterError.controlError("Error waiting for glucose response: \(error)") } guard let glucoseMessage = GlucoseRxMessage(data: glucoseData) else { - throw TransmitterError.ControlError("Unable to parse glucose response: \(glucoseData)") + throw TransmitterError.controlError("Unable to parse glucose response: \(glucoseData)") } // Update and notify @@ -281,22 +281,23 @@ public class Transmitter: BluetoothManagerDelegate { self.delegate?.transmitter(self, didRead: Glucose(glucoseMessage: glucoseMessage, timeMessage: timeMessage, activationDate: activationDate)) } - private var cryptKey: NSData? { - return "00\(ID)00\(ID)".dataUsingEncoding(NSUTF8StringEncoding) + private var cryptKey: Data? { + return "00\(ID)00\(ID)".data(using: .utf8) } - private func calculateHash(data: NSData) -> NSData? { - guard data.length == 8, let key = cryptKey else { + private func calculateHash(_ data: Data) -> Data? { + guard data.count == 8, let key = cryptKey else { return nil } - let doubleData = NSMutableData(data: data) - doubleData.appendData(data) + var doubleData = Data(capacity: data.count * 2) + doubleData.append(data) + doubleData.append(data) guard let outData = try? AESCrypt.encryptData(doubleData, usingKey: key) else { return nil } - return outData[0..<8] + return outData.subdata(in: 0..<8) } -} \ No newline at end of file +} diff --git a/xDripG5/TransmitterStatus.swift b/xDripG5/TransmitterStatus.swift index cf3043a9..109ef627 100644 --- a/xDripG5/TransmitterStatus.swift +++ b/xDripG5/TransmitterStatus.swift @@ -12,18 +12,18 @@ import Foundation public enum TransmitterStatus { public typealias RawValue = UInt8 - case OK - case LowBattery - case Unknown(RawValue) + case ok + case lowBattery + case unknown(RawValue) init(rawValue: RawValue) { switch rawValue { case 0: - self = .OK + self = .ok case 0x81: - self = .LowBattery + self = .lowBattery default: - self = .Unknown(rawValue) + self = .unknown(rawValue) } } } @@ -33,9 +33,9 @@ extension TransmitterStatus: Equatable { } public func ==(lhs: TransmitterStatus, rhs: TransmitterStatus) -> Bool { switch (lhs, rhs) { - case (.OK, .OK), (.LowBattery, .LowBattery): + case (.ok, .ok), (.lowBattery, .lowBattery): return true - case (.Unknown(let left), .Unknown(let right)) where left == right: + case (.unknown(let left), .unknown(let right)) where left == right: return true default: return false diff --git a/xDripG5Tests/GlucoseRxMessageTests.swift b/xDripG5Tests/GlucoseRxMessageTests.swift index 1d30e8d3..89a8ce9a 100644 --- a/xDripG5Tests/GlucoseRxMessageTests.swift +++ b/xDripG5Tests/GlucoseRxMessageTests.swift @@ -13,7 +13,7 @@ import XCTest class GlucoseRxMessageTests: XCTestCase { func testMessageData() { - let data = NSData(hexadecimalString: "3100680a00008a715700cc0006ffc42a")! + let data = Data(hexadecimalString: "3100680a00008a715700cc0006ffc42a")! let message = GlucoseRxMessage(data: data)! XCTAssertEqual(0, message.status) @@ -26,7 +26,7 @@ class GlucoseRxMessageTests: XCTestCase { } func testNegativeTrend() { - let data = NSData(hexadecimalString: "31006f0a0000be7957007a0006e4818d")! + let data = Data(hexadecimalString: "31006f0a0000be7957007a0006e4818d")! let message = GlucoseRxMessage(data: data)! XCTAssertEqual(0, message.status) @@ -39,7 +39,7 @@ class GlucoseRxMessageTests: XCTestCase { } func testDisplayOnly() { - let data = NSData(hexadecimalString: "3100700a0000f17a5700584006e3cee9")! + let data = Data(hexadecimalString: "3100700a0000f17a5700584006e3cee9")! let message = GlucoseRxMessage(data: data)! XCTAssertEqual(0, message.status) @@ -52,7 +52,7 @@ class GlucoseRxMessageTests: XCTestCase { } func testOldTransmitter() { - let data = NSData(hexadecimalString: "3100aa00000095a078008b00060a8b34")! + let data = Data(hexadecimalString: "3100aa00000095a078008b00060a8b34")! let message = GlucoseRxMessage(data: data)! XCTAssertEqual(0, message.status) diff --git a/xDripG5Tests/GlucoseTests.swift b/xDripG5Tests/GlucoseTests.swift index e05f84ba..43d634fa 100644 --- a/xDripG5Tests/GlucoseTests.swift +++ b/xDripG5Tests/GlucoseTests.swift @@ -13,69 +13,70 @@ import HealthKit class GlucoseTests: XCTestCase { var timeMessage: TransmitterTimeRxMessage! - let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian) - var activationDate: NSDate! + var calendar = Calendar(identifier: .gregorian) + var activationDate: Date! override func setUp() { super.setUp() - let data = NSData(hexadecimalString: "2500470272007cff710001000000fa1d")! + let data = Data(hexadecimalString: "2500470272007cff710001000000fa1d")! timeMessage = TransmitterTimeRxMessage(data: data)! - calendar?.timeZone = NSTimeZone(name: "UTC")! - activationDate = calendar?.dateWithEra(1, year: 2016, month: 10, day: 1, hour: 0, minute: 0, second: 0, nanosecond: 0)! + calendar.timeZone = TimeZone(identifier: "UTC")! + + activationDate = calendar.date(from: DateComponents(year: 2016, month: 10, day: 1))! } func testMessageData() { - let data = NSData(hexadecimalString: "3100680a00008a715700cc0006ffc42a")! + let data = Data(hexadecimalString: "3100680a00008a715700cc0006ffc42a")! let message = GlucoseRxMessage(data: data)! let glucose = Glucose(glucoseMessage: message, timeMessage: timeMessage, activationDate: activationDate) - XCTAssertEqual(TransmitterStatus.OK, glucose.status) - XCTAssertEqual(calendar?.dateWithEra(1, year: 2016, month: 12, day: 6, hour: 7, minute: 51, second: 38, nanosecond: 0)!, glucose.readDate) - XCTAssertEqual(calendar?.dateWithEra(1, year: 2016, month: 12, day: 26, hour: 11, minute: 16, second: 12, nanosecond: 0)!, glucose.sessionStartDate) + XCTAssertEqual(TransmitterStatus.ok, glucose.status) + XCTAssertEqual(calendar.date(from: DateComponents(year: 2016, month: 12, day: 6, hour: 7, minute: 51, second: 38))!, glucose.readDate) + XCTAssertEqual(calendar.date(from: DateComponents(year: 2016, month: 12, day: 26, hour: 11, minute: 16, second: 12))!, glucose.sessionStartDate) XCTAssertFalse(glucose.isDisplayOnly) - XCTAssertEqual(204, glucose.glucose?.doubleValueForUnit(HKUnit.milligramsPerDeciliter())) - XCTAssertEqual(CalibrationState.OK, glucose.state) + XCTAssertEqual(204, glucose.glucose?.doubleValue(for: HKUnit.milligramsPerDeciliter())) + XCTAssertEqual(CalibrationState.ok, glucose.state) XCTAssertEqual(-1, glucose.trend) } func testNegativeTrend() { - let data = NSData(hexadecimalString: "31006f0a0000be7957007a0006e4818d")! + let data = Data(hexadecimalString: "31006f0a0000be7957007a0006e4818d")! let message = GlucoseRxMessage(data: data)! let glucose = Glucose(glucoseMessage: message, timeMessage: timeMessage, activationDate: activationDate) - XCTAssertEqual(TransmitterStatus.OK, glucose.status) - XCTAssertEqual(calendar?.dateWithEra(1, year: 2016, month: 12, day: 6, hour: 8, minute: 26, second: 38, nanosecond: 0)!, glucose.readDate) + XCTAssertEqual(TransmitterStatus.ok, glucose.status) + XCTAssertEqual(calendar.date(from: DateComponents(year: 2016, month: 12, day: 6, hour: 8, minute: 26, second: 38))!, glucose.readDate) XCTAssertFalse(glucose.isDisplayOnly) - XCTAssertEqual(122, glucose.glucose?.doubleValueForUnit(HKUnit.milligramsPerDeciliter())) - XCTAssertEqual(CalibrationState.OK, glucose.state) + XCTAssertEqual(122, glucose.glucose?.doubleValue(for: HKUnit.milligramsPerDeciliter())) + XCTAssertEqual(CalibrationState.ok, glucose.state) XCTAssertEqual(-28, glucose.trend) } func testDisplayOnly() { - let data = NSData(hexadecimalString: "3100700a0000f17a5700584006e3cee9")! + let data = Data(hexadecimalString: "3100700a0000f17a5700584006e3cee9")! let message = GlucoseRxMessage(data: data)! let glucose = Glucose(glucoseMessage: message, timeMessage: timeMessage, activationDate: activationDate) - XCTAssertEqual(TransmitterStatus.OK, glucose.status) - XCTAssertEqual(calendar?.dateWithEra(1, year: 2016, month: 12, day: 6, hour: 8, minute: 31, second: 45, nanosecond: 0)!, glucose.readDate) + XCTAssertEqual(TransmitterStatus.ok, glucose.status) + XCTAssertEqual(calendar.date(from: DateComponents(year: 2016, month: 12, day: 6, hour: 8, minute: 31, second: 45))!, glucose.readDate) XCTAssertTrue(glucose.isDisplayOnly) - XCTAssertEqual(88, glucose.glucose?.doubleValueForUnit(HKUnit.milligramsPerDeciliter())) - XCTAssertEqual(CalibrationState.OK, glucose.state) + XCTAssertEqual(88, glucose.glucose?.doubleValue(for: HKUnit.milligramsPerDeciliter())) + XCTAssertEqual(CalibrationState.ok, glucose.state) XCTAssertEqual(-29, message.trend) } func testOldTransmitter() { - let data = NSData(hexadecimalString: "3100aa00000095a078008b00060a8b34")! + let data = Data(hexadecimalString: "3100aa00000095a078008b00060a8b34")! let message = GlucoseRxMessage(data: data)! let glucose = Glucose(glucoseMessage: message, timeMessage: timeMessage, activationDate: activationDate) - XCTAssertEqual(TransmitterStatus.OK, glucose.status) - XCTAssertEqual(calendar?.dateWithEra(1, year: 2016, month: 12, day: 31, hour: 11, minute: 57, second: 09, nanosecond: 0)!, glucose.readDate) // 90 days, status is still OK + XCTAssertEqual(TransmitterStatus.ok, glucose.status) + XCTAssertEqual(calendar.date(from: DateComponents(year: 2016, month: 12, day: 31, hour: 11, minute: 57, second: 09))!, glucose.readDate) // 90 days, status is still OK XCTAssertFalse(glucose.isDisplayOnly) - XCTAssertEqual(139, glucose.glucose?.doubleValueForUnit(HKUnit.milligramsPerDeciliter())) - XCTAssertEqual(CalibrationState.OK, glucose.state) + XCTAssertEqual(139, glucose.glucose?.doubleValue(for: HKUnit.milligramsPerDeciliter())) + XCTAssertEqual(CalibrationState.ok, glucose.state) XCTAssertEqual(10, message.trend) } diff --git a/xDripG5Tests/Info.plist b/xDripG5Tests/Info.plist index 87f0ed73..f05ffa14 100644 --- a/xDripG5Tests/Info.plist +++ b/xDripG5Tests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 0.6.0 + 0.7.0 CFBundleSignature ???? CFBundleVersion diff --git a/xDripG5Tests/NSData.swift b/xDripG5Tests/NSData.swift index e3bfb4a3..2665127e 100644 --- a/xDripG5Tests/NSData.swift +++ b/xDripG5Tests/NSData.swift @@ -9,52 +9,47 @@ import Foundation -extension NSData { - public convenience init?(hexadecimalString: String) { - if let - chars = hexadecimalString.cStringUsingEncoding(NSUTF8StringEncoding), - mutableData = NSMutableData(capacity: chars.count / 2) - { - for i in 0..(start: UnsafePointer(bytes), count: length) + let string = NSMutableString(capacity: count * 2) - let string = NSMutableString(capacity: length * 2) - - for byte in bytesCollection { + for byte in self { string.appendFormat("%02x", byte) } - + return string as String } -} \ No newline at end of file +} diff --git a/xDripG5Tests/SessionStartRxMessageTests.swift b/xDripG5Tests/SessionStartRxMessageTests.swift index 8350e721..d406289d 100644 --- a/xDripG5Tests/SessionStartRxMessageTests.swift +++ b/xDripG5Tests/SessionStartRxMessageTests.swift @@ -13,7 +13,7 @@ import XCTest class SessionStartRxMessageTests: XCTestCase { func testSuccessfulStart() { - var data = NSData(hexadecimalString: "2700014bf871004bf87100e9f8710095d9")! + var data = Data(hexadecimalString: "2700014bf871004bf87100e9f8710095d9")! var message = SessionStartRxMessage(data: data)! XCTAssertEqual(0, message.status) @@ -22,7 +22,7 @@ class SessionStartRxMessageTests: XCTestCase { XCTAssertEqual(7469131, message.sessionStartTime) XCTAssertEqual(7469289, message.transmitterTime) - data = NSData(hexadecimalString: "2700012bfd71002bfd710096fd71000f6a")! + data = Data(hexadecimalString: "2700012bfd71002bfd710096fd71000f6a")! message = SessionStartRxMessage(data: data)! XCTAssertEqual(0, message.status) @@ -31,7 +31,7 @@ class SessionStartRxMessageTests: XCTestCase { XCTAssertEqual(7470379, message.sessionStartTime) XCTAssertEqual(7470486, message.transmitterTime) - data = NSData(hexadecimalString: "2700017cff71007cff7100eeff7100aeed")! + data = Data(hexadecimalString: "2700017cff71007cff7100eeff7100aeed")! message = SessionStartRxMessage(data: data)! XCTAssertEqual(0, message.status) diff --git a/xDripG5Tests/SessionStopRxMessageTests.swift b/xDripG5Tests/SessionStopRxMessageTests.swift index d6f34b23..ceec54f4 100644 --- a/xDripG5Tests/SessionStopRxMessageTests.swift +++ b/xDripG5Tests/SessionStopRxMessageTests.swift @@ -13,7 +13,7 @@ import XCTest class SessionStopRxMessageTests: XCTestCase { func testSuccessfulStop() { - var data = NSData(hexadecimalString: "29000128027200ffffffff47027200ba85")! + var data = Data(hexadecimalString: "29000128027200ffffffff47027200ba85")! var message = SessionStopRxMessage(data: data)! XCTAssertEqual(0, message.status) @@ -22,7 +22,7 @@ class SessionStopRxMessageTests: XCTestCase { XCTAssertEqual(0xffffffff, message.sessionStartTime) XCTAssertEqual(7471687, message.transmitterTime) - data = NSData(hexadecimalString: "2900013ffe7100ffffffffc2fe71008268")! + data = Data(hexadecimalString: "2900013ffe7100ffffffffc2fe71008268")! message = SessionStopRxMessage(data: data)! XCTAssertEqual(0, message.status) @@ -31,7 +31,7 @@ class SessionStopRxMessageTests: XCTestCase { XCTAssertEqual(0xffffffff, message.sessionStartTime) XCTAssertEqual(7470786, message.transmitterTime) - data = NSData(hexadecimalString: "290001f5fb7100ffffffff6afc7100fa8a")! + data = Data(hexadecimalString: "290001f5fb7100ffffffff6afc7100fa8a")! message = SessionStopRxMessage(data: data)! XCTAssertEqual(0, message.status) diff --git a/xDripG5Tests/TransmitterTimeRxMessageTests.swift b/xDripG5Tests/TransmitterTimeRxMessageTests.swift index eaad0eff..cca72c71 100644 --- a/xDripG5Tests/TransmitterTimeRxMessageTests.swift +++ b/xDripG5Tests/TransmitterTimeRxMessageTests.swift @@ -13,21 +13,21 @@ import XCTest class TransmitterTimeRxMessageTests: XCTestCase { func testNoSession() { - var data = NSData(hexadecimalString: "2500e8f87100ffffffff010000000a70")! + var data = Data(hexadecimalString: "2500e8f87100ffffffff010000000a70")! var message = TransmitterTimeRxMessage(data: data)! XCTAssertEqual(0, message.status) XCTAssertEqual(7469288, message.currentTime) XCTAssertEqual(0xffffffff, message.sessionStartTime) - data = NSData(hexadecimalString: "250096fd7100ffffffff01000000226d")! + data = Data(hexadecimalString: "250096fd7100ffffffff01000000226d")! message = TransmitterTimeRxMessage(data: data)! XCTAssertEqual(0, message.status) XCTAssertEqual(7470486, message.currentTime) XCTAssertEqual(0xffffffff, message.sessionStartTime) - data = NSData(hexadecimalString: "2500eeff7100ffffffff010000008952")! + data = Data(hexadecimalString: "2500eeff7100ffffffff010000008952")! message = TransmitterTimeRxMessage(data: data)! XCTAssertEqual(0, message.status) @@ -36,7 +36,7 @@ class TransmitterTimeRxMessageTests: XCTestCase { } func testInSession() { - let data = NSData(hexadecimalString: "2500470272007cff710001000000fa1d")! + let data = Data(hexadecimalString: "2500470272007cff710001000000fa1d")! let message = TransmitterTimeRxMessage(data: data)! XCTAssertEqual(0, message.status)