From 0dd39e8f641cbcae1def30710e06bea43e660fbf Mon Sep 17 00:00:00 2001 From: Nathan Racklyeft Date: Thu, 29 Sep 2016 20:54:36 -0700 Subject: [PATCH 1/5] Changing the observation strategy to be non-linear (#45) Fixes #44 --- Example/Podfile.lock | 2 +- Example/xDripG5.xcodeproj/project.pbxproj | 6 +- Example/xDripG5/AppDelegate.swift | 8 +++ Example/xDripG5/Data.swift | 22 +++++++ Example/xDripG5/ViewController.swift | 5 ++ xDripG5.xcodeproj/project.pbxproj | 14 ++++- xDripG5/BluetoothManager.swift | 15 ++++- .../Messages/CalibrationDataRxMessage.swift | 24 +++++++ xDripG5/Transmitter.swift | 62 ++++++++++--------- .../CalibrationDataRxMessageTests.swift | 30 +++++++++ 10 files changed, 151 insertions(+), 37 deletions(-) create mode 100644 Example/xDripG5/Data.swift create mode 100644 xDripG5/Messages/CalibrationDataRxMessage.swift create mode 100644 xDripG5Tests/CalibrationDataRxMessageTests.swift diff --git a/Example/Podfile.lock b/Example/Podfile.lock index e87f3d63..ae846bc7 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -13,4 +13,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 6b30cba971694d5258509315fb52eb645c9bc5e3 -COCOAPODS: 1.1.0.beta.2 +COCOAPODS: 1.1.0.rc.2 diff --git a/Example/xDripG5.xcodeproj/project.pbxproj b/Example/xDripG5.xcodeproj/project.pbxproj index be841e30..8a1bd720 100644 --- a/Example/xDripG5.xcodeproj/project.pbxproj +++ b/Example/xDripG5.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 06C991A3D94948120AD2A278 /* Pods_xDripG5_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42011659993839B43D24C553 /* Pods_xDripG5_Example.framework */; }; + 43846AC21D8F812A00799272 /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43846AC11D8F812A00799272 /* Data.swift */; }; 439FCA211C332AA4007DE84C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 439FCA1F1C332AA4007DE84C /* LaunchScreen.storyboard */; }; 439FCA231C332AE5007DE84C /* NSUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 439FCA221C332AE5007DE84C /* NSUserDefaults.swift */; }; 43E3979F1D569B340028E321 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E3979E1D569B340028E321 /* HKUnit.swift */; }; @@ -19,6 +20,7 @@ /* Begin PBXFileReference section */ 42011659993839B43D24C553 /* Pods_xDripG5_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_xDripG5_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 43846AC11D8F812A00799272 /* Data.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = ""; }; 439FCA201C332AA4007DE84C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 439FCA221C332AE5007DE84C /* NSUserDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSUserDefaults.swift; sourceTree = ""; }; 43E3979E1D569B340028E321 /* HKUnit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HKUnit.swift; path = ../../xDripG5/HKUnit.swift; sourceTree = ""; }; @@ -78,6 +80,7 @@ isa = PBXGroup; children = ( 607FACD51AFB9204008FA782 /* AppDelegate.swift */, + 43846AC11D8F812A00799272 /* Data.swift */, 43E3979E1D569B340028E321 /* HKUnit.swift */, 439FCA221C332AE5007DE84C /* NSUserDefaults.swift */, 607FACD71AFB9204008FA782 /* ViewController.swift */, @@ -246,6 +249,7 @@ buildActionMask = 2147483647; files = ( 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, + 43846AC21D8F812A00799272 /* Data.swift in Sources */, 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 43E3979F1D569B340028E321 /* HKUnit.swift in Sources */, 439FCA231C332AE5007DE84C /* NSUserDefaults.swift in Sources */, @@ -365,7 +369,6 @@ 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"; @@ -381,7 +384,6 @@ 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"; diff --git a/Example/xDripG5/AppDelegate.swift b/Example/xDripG5/AppDelegate.swift index 4cf8a5b8..f230f6d9 100644 --- a/Example/xDripG5/AppDelegate.swift +++ b/Example/xDripG5/AppDelegate.swift @@ -87,4 +87,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate, TransmitterDelegate { } } } + + func transmitter(_ transmitter: Transmitter, didReadUnknownData data: Data) { + if let vc = window?.rootViewController as? TransmitterDelegate { + DispatchQueue.main.async { + vc.transmitter(transmitter, didReadUnknownData: data) + } + } + } } diff --git a/Example/xDripG5/Data.swift b/Example/xDripG5/Data.swift new file mode 100644 index 00000000..81d92e53 --- /dev/null +++ b/Example/xDripG5/Data.swift @@ -0,0 +1,22 @@ +// +// Data.swift +// xDripG5 +// +// Created by Nate Racklyeft on 9/18/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import Foundation + + +extension Data { + var hexadecimalString: String { + let string = NSMutableString(capacity: count * 2) + + for byte in self { + string.appendFormat("%02x", byte) + } + + return string as String + } +} diff --git a/Example/xDripG5/ViewController.swift b/Example/xDripG5/ViewController.swift index 7cb49e21..faef5334 100644 --- a/Example/xDripG5/ViewController.swift +++ b/Example/xDripG5/ViewController.swift @@ -119,6 +119,11 @@ class ViewController: UIViewController, TransmitterDelegate, UITextFieldDelegate let date = glucose.readDate subtitleLabel.text = DateFormatter.localizedString(from: date, dateStyle: .none, timeStyle: .long) } + + func transmitter(_ transmitter: Transmitter, didReadUnknownData data: Data) { + titleLabel.text = NSLocalizedString("Unknown Data", comment: "Title displayed during unknown data response") + subtitleLabel.text = data.hexadecimalString + } } diff --git a/xDripG5.xcodeproj/project.pbxproj b/xDripG5.xcodeproj/project.pbxproj index 2b5754e9..4f3547e7 100644 --- a/xDripG5.xcodeproj/project.pbxproj +++ b/xDripG5.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ 430D64C51CB7846A00FCA750 /* NSData+CRC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 430D64C41CB7846A00FCA750 /* NSData+CRC.swift */; }; 43538C111D81220F0071CA5E /* NSData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE101C350B2800005705 /* NSData.swift */; }; + 43846AC61D8F896C00799272 /* CalibrationDataRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43846AC51D8F896C00799272 /* CalibrationDataRxMessage.swift */; }; + 43846AC81D8F89BE00799272 /* CalibrationDataRxMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43846AC71D8F89BE00799272 /* CalibrationDataRxMessageTests.swift */; }; 43CABDF71C3506F100005705 /* xDripG5.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CABDF61C3506F100005705 /* xDripG5.h */; settings = {ATTRIBUTES = (Public, ); }; }; 43CABDFE1C3506F100005705 /* xDripG5.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CABDF31C3506F100005705 /* xDripG5.framework */; }; 43CABE121C350B2800005705 /* BluetoothManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE0E1C350B2800005705 /* BluetoothManager.swift */; }; @@ -74,6 +76,8 @@ /* Begin PBXFileReference section */ 430D64C41CB7846A00FCA750 /* NSData+CRC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSData+CRC.swift"; sourceTree = ""; }; + 43846AC51D8F896C00799272 /* CalibrationDataRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CalibrationDataRxMessage.swift; sourceTree = ""; }; + 43846AC71D8F89BE00799272 /* CalibrationDataRxMessageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CalibrationDataRxMessageTests.swift; sourceTree = ""; }; 43CABDF31C3506F100005705 /* xDripG5.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = xDripG5.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 43CABDF61C3506F100005705 /* xDripG5.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = xDripG5.h; sourceTree = ""; }; 43CABDF81C3506F100005705 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -182,13 +186,14 @@ 43CABE011C3506F100005705 /* xDripG5Tests */ = { isa = PBXGroup; children = ( - 43E397901D5692080028E321 /* GlucoseTests.swift */, + 43846AC71D8F89BE00799272 /* CalibrationDataRxMessageTests.swift */, 43DC87C11C8B520F005BC30D /* GlucoseRxMessageTests.swift */, + 43E397901D5692080028E321 /* GlucoseTests.swift */, 43CABE041C3506F100005705 /* Info.plist */, 43DC87BF1C8B509B005BC30D /* NSData.swift */, - 43F82BCB1D035AA4006F5DD7 /* TransmitterTimeRxMessageTests.swift */, - 43F82BD11D037040006F5DD7 /* SessionStopRxMessageTests.swift */, 43F82BD31D037227006F5DD7 /* SessionStartRxMessageTests.swift */, + 43F82BD11D037040006F5DD7 /* SessionStopRxMessageTests.swift */, + 43F82BCB1D035AA4006F5DD7 /* TransmitterTimeRxMessageTests.swift */, ); path = xDripG5Tests; sourceTree = ""; @@ -203,6 +208,7 @@ 43CE7CCB1CA73BCC003CC1B0 /* BatteryStatusTxMessage.swift */, 43CABE1B1C350B3D00005705 /* BondRequestTxMessage.swift */, 43CE7CD11CA73CBC003CC1B0 /* CalibrateGlucoseTxMessage.swift */, + 43846AC51D8F896C00799272 /* CalibrationDataRxMessage.swift */, 43CABE1C1C350B3D00005705 /* DisconnectTxMessage.swift */, 43CE7CC71CA73AEB003CC1B0 /* FirmwareVersionTxMessage.swift */, 43CE7CD31CA73CE8003CC1B0 /* GlucoseHistoryTxMessage.swift */, @@ -343,6 +349,7 @@ 43CABE261C350B3D00005705 /* AuthStatusRxMessage.swift in Sources */, 43CE7CD41CA73CE8003CC1B0 /* GlucoseHistoryTxMessage.swift in Sources */, 43E397931D56950C0028E321 /* HKUnit.swift in Sources */, + 43846AC61D8F896C00799272 /* CalibrationDataRxMessage.swift in Sources */, 43CE7CD01CA73C57003CC1B0 /* SessionStopTxMessage.swift in Sources */, 43CABE2A1C350B3D00005705 /* GlucoseTxMessage.swift in Sources */, 43CE7CC81CA73AEB003CC1B0 /* FirmwareVersionTxMessage.swift in Sources */, @@ -373,6 +380,7 @@ files = ( 43F82BCC1D035AA4006F5DD7 /* TransmitterTimeRxMessageTests.swift in Sources */, 43F82BD41D037227006F5DD7 /* SessionStartRxMessageTests.swift in Sources */, + 43846AC81D8F89BE00799272 /* CalibrationDataRxMessageTests.swift in Sources */, 43DC87C01C8B509B005BC30D /* NSData.swift in Sources */, 43F82BD21D037040006F5DD7 /* SessionStopRxMessageTests.swift in Sources */, 43E397911D5692080028E321 /* GlucoseTests.swift in Sources */, diff --git a/xDripG5/BluetoothManager.swift b/xDripG5/BluetoothManager.swift index 2db9cef8..99da4fed 100644 --- a/xDripG5/BluetoothManager.swift +++ b/xDripG5/BluetoothManager.swift @@ -29,6 +29,12 @@ protocol BluetoothManagerDelegate: class { - returns: True if the peripheral should connect */ func bluetoothManager(_ manager: BluetoothManager, shouldConnectPeripheral peripheral: CBPeripheral) -> Bool + + /// Tells the delegate that the bluetooth manager received new data in the control characteristic. + /// + /// - parameter manager: The bluetooth manager + /// - parameter didReceiveControlResponse: The data received on the control characteristic + func bluetoothManager(_ manager: BluetoothManager, didReceiveControlResponse response: Data) } @@ -422,7 +428,6 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate } func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { - operationLock.lock() if operationConditions.remove(.valueUpdate(characteristic: characteristic, firstByte: characteristic.value?[0])) != nil || @@ -436,11 +441,15 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate } operationLock.unlock() + + if let data = characteristic.value { + delegate?.bluetoothManager(self, didReceiveControlResponse: data) + } } func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { - self.operationLock.lock() + operationLock.lock() if operationConditions.remove(.writeUpdate(characteristic: characteristic)) != nil { operationError = error @@ -450,7 +459,7 @@ class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate } } - self.operationLock.unlock() + operationLock.unlock() } } diff --git a/xDripG5/Messages/CalibrationDataRxMessage.swift b/xDripG5/Messages/CalibrationDataRxMessage.swift new file mode 100644 index 00000000..25032634 --- /dev/null +++ b/xDripG5/Messages/CalibrationDataRxMessage.swift @@ -0,0 +1,24 @@ +// +// CalibrationDataRxMessage.swift +// Pods +// +// Created by Nate Racklyeft on 9/18/16. +// +// + +import Foundation + + +struct CalibrationDataRxMessage: TransmitterRxMessage { + static let opcode: UInt8 = 0x33 + + init?(data: Data) { + guard data.count == 19 && data.crcValid() else { + return nil + } + + guard data[0] == type(of: self).opcode else { + return nil + } + } +} diff --git a/xDripG5/Transmitter.swift b/xDripG5/Transmitter.swift index e222ceba..692ca235 100644 --- a/xDripG5/Transmitter.swift +++ b/xDripG5/Transmitter.swift @@ -14,6 +14,8 @@ public protocol TransmitterDelegate: class { func transmitter(_ transmitter: Transmitter, didError error: Error) func transmitter(_ transmitter: Transmitter, didRead glucose: Glucose) + + func transmitter(_ transmitter: Transmitter, didReadUnknownData data: Data) } @@ -31,6 +33,8 @@ public final class Transmitter: BluetoothManagerDelegate { /// The initial activation date of the transmitter public private(set) var activationDate: Date? + private var lastTimeMessage: TransmitterTimeRxMessage? + public var passiveModeEnabled: Bool public weak var delegate: TransmitterDelegate? @@ -123,6 +127,35 @@ public final class Transmitter: BluetoothManagerDelegate { } } + func bluetoothManager(_ manager: BluetoothManager, didReceiveControlResponse response: Data) { + guard passiveModeEnabled else { return } + + guard response.count > 0 else { return } + + switch response[0] { + case GlucoseRxMessage.opcode: + if let glucoseMessage = GlucoseRxMessage(data: response), + let timeMessage = lastTimeMessage, + let activationDate = activationDate + { + self.delegate?.transmitter(self, didRead: Glucose(glucoseMessage: glucoseMessage, timeMessage: timeMessage, activationDate: activationDate)) + return + } + case CalibrationDataRxMessage.opcode, SessionStartRxMessage.opcode, SessionStopRxMessage.opcode: + return // Ignore these messages + case TransmitterTimeRxMessage.opcode: + if let timeMessage = TransmitterTimeRxMessage(data: response) { + self.activationDate = Date(timeIntervalSinceNow: -TimeInterval(timeMessage.currentTime)) + self.lastTimeMessage = timeMessage + return + } + default: + break + } + + delegate?.transmitter(self, didReadUnknownData: response) + } + // MARK: - Helpers private func authenticate() throws { @@ -235,6 +268,7 @@ public final class Transmitter: BluetoothManagerDelegate { } // Update and notify + self.lastTimeMessage = timeMessage self.activationDate = activationDate self.delegate?.transmitter(self, didRead: Glucose(glucoseMessage: glucoseMessage, timeMessage: timeMessage, activationDate: activationDate)) @@ -251,34 +285,6 @@ public final class Transmitter: BluetoothManagerDelegate { } catch let error { throw TransmitterError.controlError("Error enabling notification: \(error)") } - - let timeData: Data - do { - timeData = try bluetoothManager.waitForCharacteristicValueUpdate(.Control, expectingFirstByte: TransmitterTimeRxMessage.opcode) - } catch let 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)") - } - - let activationDate = Date(timeIntervalSinceNow: -TimeInterval(timeMessage.currentTime)) - - let glucoseData: Data - do { - glucoseData = try bluetoothManager.waitForCharacteristicValueUpdate(.Control, expectingFirstByte: GlucoseRxMessage.opcode) - } catch let 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)") - } - - // Update and notify - self.activationDate = activationDate - self.delegate?.transmitter(self, didRead: Glucose(glucoseMessage: glucoseMessage, timeMessage: timeMessage, activationDate: activationDate)) } private var cryptKey: Data? { diff --git a/xDripG5Tests/CalibrationDataRxMessageTests.swift b/xDripG5Tests/CalibrationDataRxMessageTests.swift new file mode 100644 index 00000000..5125bd7b --- /dev/null +++ b/xDripG5Tests/CalibrationDataRxMessageTests.swift @@ -0,0 +1,30 @@ +// +// CalibrationDataRxMessageTests.swift +// xDripG5 +// +// Created by Nate Racklyeft on 9/18/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import XCTest +@testable import xDripG5 + + +class CalibrationDataRxMessageTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testMessage() { + let data = Data(hexadecimalString: "33002b290090012900ae00800050e929001225")! + XCTAssertNotNil(CalibrationDataRxMessage(data: data)) + } + +} From b55d67b35c09a3012fed237e1713ed809c9c80ff Mon Sep 17 00:00:00 2001 From: Nathan Racklyeft Date: Thu, 29 Sep 2016 21:17:14 -0700 Subject: [PATCH 2/5] Adding some new rx messages (#47) --- xDripG5.xcodeproj/project.pbxproj | 8 +++++ xDripG5/Messages/BatteryStatusTxMessage.swift | 2 ++ .../TransmitterVersionRxMessage.swift | 30 +++++++++++++++++++ xDripG5/NSData.swift | 4 +-- .../TransmitterVersionRxMessageTests.swift | 22 ++++++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 xDripG5/Messages/TransmitterVersionRxMessage.swift create mode 100644 xDripG5Tests/TransmitterVersionRxMessageTests.swift diff --git a/xDripG5.xcodeproj/project.pbxproj b/xDripG5.xcodeproj/project.pbxproj index 4f3547e7..bfff2e26 100644 --- a/xDripG5.xcodeproj/project.pbxproj +++ b/xDripG5.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 43538C111D81220F0071CA5E /* NSData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE101C350B2800005705 /* NSData.swift */; }; 43846AC61D8F896C00799272 /* CalibrationDataRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43846AC51D8F896C00799272 /* CalibrationDataRxMessage.swift */; }; 43846AC81D8F89BE00799272 /* CalibrationDataRxMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43846AC71D8F89BE00799272 /* CalibrationDataRxMessageTests.swift */; }; + 43880F981D9E19FC009061A8 /* TransmitterVersionRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43880F971D9E19FC009061A8 /* TransmitterVersionRxMessage.swift */; }; + 43880F9A1D9E1BD7009061A8 /* TransmitterVersionRxMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43880F991D9E1BD7009061A8 /* TransmitterVersionRxMessageTests.swift */; }; 43CABDF71C3506F100005705 /* xDripG5.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CABDF61C3506F100005705 /* xDripG5.h */; settings = {ATTRIBUTES = (Public, ); }; }; 43CABDFE1C3506F100005705 /* xDripG5.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CABDF31C3506F100005705 /* xDripG5.framework */; }; 43CABE121C350B2800005705 /* BluetoothManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CABE0E1C350B2800005705 /* BluetoothManager.swift */; }; @@ -78,6 +80,8 @@ 430D64C41CB7846A00FCA750 /* NSData+CRC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSData+CRC.swift"; sourceTree = ""; }; 43846AC51D8F896C00799272 /* CalibrationDataRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CalibrationDataRxMessage.swift; sourceTree = ""; }; 43846AC71D8F89BE00799272 /* CalibrationDataRxMessageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CalibrationDataRxMessageTests.swift; sourceTree = ""; }; + 43880F971D9E19FC009061A8 /* TransmitterVersionRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterVersionRxMessage.swift; sourceTree = ""; }; + 43880F991D9E1BD7009061A8 /* TransmitterVersionRxMessageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterVersionRxMessageTests.swift; sourceTree = ""; }; 43CABDF31C3506F100005705 /* xDripG5.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = xDripG5.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 43CABDF61C3506F100005705 /* xDripG5.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = xDripG5.h; sourceTree = ""; }; 43CABDF81C3506F100005705 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -194,6 +198,7 @@ 43F82BD31D037227006F5DD7 /* SessionStartRxMessageTests.swift */, 43F82BD11D037040006F5DD7 /* SessionStopRxMessageTests.swift */, 43F82BCB1D035AA4006F5DD7 /* TransmitterTimeRxMessageTests.swift */, + 43880F991D9E1BD7009061A8 /* TransmitterVersionRxMessageTests.swift */, ); path = xDripG5Tests; sourceTree = ""; @@ -223,6 +228,7 @@ 43CABE211C350B3D00005705 /* TransmitterTimeRxMessage.swift */, 43CABE221C350B3D00005705 /* TransmitterTimeTxMessage.swift */, 43CE7CC91CA73B94003CC1B0 /* TransmitterVersionTxMessage.swift */, + 43880F971D9E19FC009061A8 /* TransmitterVersionRxMessage.swift */, ); path = Messages; sourceTree = ""; @@ -357,6 +363,7 @@ 43EEA7121D14DC0800CBBDA0 /* AESCrypt.m in Sources */, 43CE7CCE1CA73C22003CC1B0 /* SessionStartTxMessage.swift in Sources */, 43CABE2E1C350B3D00005705 /* TransmitterTimeTxMessage.swift in Sources */, + 43880F981D9E19FC009061A8 /* TransmitterVersionRxMessage.swift in Sources */, 43538C111D81220F0071CA5E /* NSData.swift in Sources */, 43CABE2C1C350B3D00005705 /* TransmitterMessage.swift in Sources */, 43CABE131C350B2800005705 /* BluetoothServices.swift in Sources */, @@ -384,6 +391,7 @@ 43DC87C01C8B509B005BC30D /* NSData.swift in Sources */, 43F82BD21D037040006F5DD7 /* SessionStopRxMessageTests.swift in Sources */, 43E397911D5692080028E321 /* GlucoseTests.swift in Sources */, + 43880F9A1D9E1BD7009061A8 /* TransmitterVersionRxMessageTests.swift in Sources */, 43DC87C21C8B520F005BC30D /* GlucoseRxMessageTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/xDripG5/Messages/BatteryStatusTxMessage.swift b/xDripG5/Messages/BatteryStatusTxMessage.swift index 0a768087..81e48dcd 100644 --- a/xDripG5/Messages/BatteryStatusTxMessage.swift +++ b/xDripG5/Messages/BatteryStatusTxMessage.swift @@ -11,4 +11,6 @@ import Foundation struct BatteryStatusTxMessage { let opcode: UInt8 = 0x22 + + // Response: 23003c012f01cd021f247bae } diff --git a/xDripG5/Messages/TransmitterVersionRxMessage.swift b/xDripG5/Messages/TransmitterVersionRxMessage.swift new file mode 100644 index 00000000..fa26c1c5 --- /dev/null +++ b/xDripG5/Messages/TransmitterVersionRxMessage.swift @@ -0,0 +1,30 @@ +// +// TransmitterVersionRxMessage.swift +// xDripG5 +// +// Created by Nate Racklyeft on 9/29/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import Foundation + + +struct TransmitterVersionRxMessage: TransmitterRxMessage { + static let opcode: UInt8 = 0x4b + let status: UInt8 + let firmwareVersion: [UInt8] + + init?(data: Data) { + guard data.count == 19 && data.crcValid() else { + return nil + } + + guard data[0] == type(of: self).opcode else { + return nil + } + + status = data[1] + firmwareVersion = data[2..<6] + } + +} diff --git a/xDripG5/NSData.swift b/xDripG5/NSData.swift index c823c93e..a1ee1c34 100644 --- a/xDripG5/NSData.swift +++ b/xDripG5/NSData.swift @@ -45,14 +45,14 @@ public extension Data { return dataArray } - +*/ subscript(range: Range) -> [UInt8] { var dataArray = [UInt8](repeating: 0, count: range.count) self.copyBytes(to: &dataArray, from: range) return dataArray } - +/* subscript(range: Range) -> [UInt16] { var dataArray = [UInt16](repeating: 0, count: range.count / 2) let buffer = UnsafeMutableBufferPointer(start: &dataArray, count: range.count) diff --git a/xDripG5Tests/TransmitterVersionRxMessageTests.swift b/xDripG5Tests/TransmitterVersionRxMessageTests.swift new file mode 100644 index 00000000..d4f40f72 --- /dev/null +++ b/xDripG5Tests/TransmitterVersionRxMessageTests.swift @@ -0,0 +1,22 @@ +// +// TransmitterVersionRxMessageTests.swift +// xDripG5 +// +// Created by Nate Racklyeft on 9/29/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import XCTest +@testable import xDripG5 + +class TransmitterVersionRxMessageTests: XCTestCase { + + func testRxMessage() { + let data = Data(hexadecimalString: "4b0001000011df2900005100037000f00009b6")! + let message = TransmitterVersionRxMessage(data: data)! + + XCTAssertEqual(0, message.status) + XCTAssertEqual([1, 0, 0, 17], message.firmwareVersion) + } + +} From 426546e1913b3774ea603c2a1035a9c53ecc7a6e Mon Sep 17 00:00:00 2001 From: Nathan Racklyeft Date: Thu, 29 Sep 2016 21:18:06 -0700 Subject: [PATCH 3/5] New version --- xDripG5.xcodeproj/project.pbxproj | 8 ++++---- xDripG5/Info.plist | 2 +- xDripG5Tests/Info.plist | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/xDripG5.xcodeproj/project.pbxproj b/xDripG5.xcodeproj/project.pbxproj index bfff2e26..9ed66df0 100644 --- a/xDripG5.xcodeproj/project.pbxproj +++ b/xDripG5.xcodeproj/project.pbxproj @@ -428,7 +428,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 14; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -478,7 +478,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 14; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -508,7 +508,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 13; + DYLIB_CURRENT_VERSION = 14; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = xDripG5/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -528,7 +528,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 13; + DYLIB_CURRENT_VERSION = 14; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = xDripG5/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/xDripG5/Info.plist b/xDripG5/Info.plist index 3157e479..5d7827c2 100644 --- a/xDripG5/Info.plist +++ b/xDripG5/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.7.0 + 0.8.0 CFBundleSignature ???? CFBundleVersion diff --git a/xDripG5Tests/Info.plist b/xDripG5Tests/Info.plist index f05ffa14..ab895996 100644 --- a/xDripG5Tests/Info.plist +++ b/xDripG5Tests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 0.7.0 + 0.8.0 CFBundleSignature ???? CFBundleVersion From 85f04263934b1059f27bded427cb31489e2d5689 Mon Sep 17 00:00:00 2001 From: Nathan Racklyeft Date: Thu, 29 Sep 2016 21:30:12 -0700 Subject: [PATCH 4/5] Updating podspec --- Example/Podfile.lock | 4 ++-- xDripG5.podspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Example/Podfile.lock b/Example/Podfile.lock index ae846bc7..64948e5c 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - xDripG5 (0.7.0) + - xDripG5 (0.8.0) DEPENDENCIES: - xDripG5 (from `../`) @@ -9,7 +9,7 @@ EXTERNAL SOURCES: :path: ../ SPEC CHECKSUMS: - xDripG5: b0bfa28e1dc510799d919ab6a67badb56a024247 + xDripG5: 28b4af83bd6794e5131a02e6d909fbf7442b5340 PODFILE CHECKSUM: 6b30cba971694d5258509315fb52eb645c9bc5e3 diff --git a/xDripG5.podspec b/xDripG5.podspec index 21fc5af1..4b223466 100644 --- a/xDripG5.podspec +++ b/xDripG5.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "xDripG5" - s.version = "0.7.0" + s.version = "0.8.0" s.summary = "An interface for communicating with the G5 glucose transmitter over Bluetooth." s.description = <<-DESC From b9ca1d31fd71fae9936f234066e48439b03ed362 Mon Sep 17 00:00:00 2001 From: Nathan Racklyeft Date: Thu, 29 Sep 2016 21:44:34 -0700 Subject: [PATCH 5/5] Updating URLs --- Example/Podfile.lock | 2 +- README.md | 6 +++--- xDripG5.podspec | 5 ++--- xDripG5.xcodeproj/project.pbxproj | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 64948e5c..9d30a5a1 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -9,7 +9,7 @@ EXTERNAL SOURCES: :path: ../ SPEC CHECKSUMS: - xDripG5: 28b4af83bd6794e5131a02e6d909fbf7442b5340 + xDripG5: 8779a4f495fd8eb81a3d75457afe9b95fb52f61d PODFILE CHECKSUM: 6b30cba971694d5258509315fb52eb645c9bc5e3 diff --git a/README.md b/README.md index 4373d6cf..28351e65 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # xDripG5 -[![CI Status](http://img.shields.io/travis/loudnate/xDripG5.svg?style=flat)](https://travis-ci.org/loudnate/xDripG5) +[![CI Status](http://img.shields.io/travis/LoopKit/xDripG5.svg?style=flat)](https://travis-ci.org/LoopKit/xDripG5) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Version](https://img.shields.io/cocoapods/v/xDripG5.svg?style=flat)](http://cocoapods.org/pods/xDripG5) [![License](https://img.shields.io/cocoapods/l/xDripG5.svg?style=flat)](http://cocoapods.org/pods/xDripG5) @@ -21,7 +21,7 @@ This framework connects to a G5 Mobile Transmitter via Bluetooth LE. It does not xDripG5 is available through [Carthage](https://github.com/Carthage/Carthage). To install it, add the following line to your Cartfile: ```ruby -github "loudnate/xDripG5" +github "LoopKit/xDripG5" ``` Note that you'll need to confgure your target to link against `CommonCrypto.framework` in addition to `xDripG5.framework` @@ -48,7 +48,7 @@ If you plan to run your app alongside the G5 Mobile application, make sure to se ## Code of Conduct -Please note that this project is released with a [Contributor Code of Conduct](https://github.com/loudnate/LoopKit/blob/master/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. +Please note that this project is released with a [Contributor Code of Conduct](https://github.com/LoopKit/LoopKit/blob/master/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. ## License diff --git a/xDripG5.podspec b/xDripG5.podspec index 4b223466..8374f388 100644 --- a/xDripG5.podspec +++ b/xDripG5.podspec @@ -11,11 +11,10 @@ By using this framework in your own app, you can get access to your glucose read Please note this project is neither created nor backed by Dexcom, Inc. Use of this software is not intended for therapy. DESC - s.homepage = "https://github.com/loudnate/xDripG5" + s.homepage = "https://github.com/LoopKit/xDripG5" s.license = 'MIT' s.author = { "Nathan Racklyeft" => "loudnate@gmail.com" } - s.source = { :git => "https://github.com/loudnate/xDripG5.git", :tag => s.version.to_s } - s.social_media_url = 'https://twitter.com/loudnate' + s.source = { :git => "https://github.com/LoopKit/xDripG5.git", :tag => s.version.to_s } s.platform = :ios, '9.3' s.requires_arc = true diff --git a/xDripG5.xcodeproj/project.pbxproj b/xDripG5.xcodeproj/project.pbxproj index 9ed66df0..371c615f 100644 --- a/xDripG5.xcodeproj/project.pbxproj +++ b/xDripG5.xcodeproj/project.pbxproj @@ -293,7 +293,7 @@ attributes = { LastSwiftUpdateCheck = 0730; LastUpgradeCheck = 0800; - ORGANIZATIONNAME = "Nathan Racklyeft"; + ORGANIZATIONNAME = "LoopKit Authors"; TargetAttributes = { 43CABDF21C3506F100005705 = { CreatedOnToolsVersion = 7.2;