diff --git a/xDripG5.xcodeproj/project.pbxproj b/xDripG5.xcodeproj/project.pbxproj index 4d057a32..7465e57b 100644 --- a/xDripG5.xcodeproj/project.pbxproj +++ b/xDripG5.xcodeproj/project.pbxproj @@ -39,6 +39,11 @@ 43CE7CDC1CA77468003CC1B0 /* TransmitterStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43CE7CDB1CA77468003CC1B0 /* TransmitterStatus.swift */; }; 43DC87C01C8B509B005BC30D /* NSData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DC87BF1C8B509B005BC30D /* NSData.swift */; }; 43DC87C21C8B520F005BC30D /* GlucoseRxMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43DC87C11C8B520F005BC30D /* GlucoseRxMessageTests.swift */; }; + 43F82BCC1D035AA4006F5DD7 /* TransmitterTimeRxMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F82BCB1D035AA4006F5DD7 /* TransmitterTimeRxMessageTests.swift */; }; + 43F82BCE1D035D5C006F5DD7 /* SessionStartRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F82BCD1D035D5C006F5DD7 /* SessionStartRxMessage.swift */; }; + 43F82BD01D035D68006F5DD7 /* SessionStopRxMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F82BCF1D035D68006F5DD7 /* SessionStopRxMessage.swift */; }; + 43F82BD21D037040006F5DD7 /* SessionStopRxMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F82BD11D037040006F5DD7 /* SessionStopRxMessageTests.swift */; }; + 43F82BD41D037227006F5DD7 /* SessionStartRxMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F82BD31D037227006F5DD7 /* SessionStartRxMessageTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -98,6 +103,11 @@ 43CE7CDB1CA77468003CC1B0 /* TransmitterStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterStatus.swift; sourceTree = ""; }; 43DC87BF1C8B509B005BC30D /* NSData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSData.swift; sourceTree = ""; }; 43DC87C11C8B520F005BC30D /* GlucoseRxMessageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlucoseRxMessageTests.swift; sourceTree = ""; }; + 43F82BCB1D035AA4006F5DD7 /* TransmitterTimeRxMessageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransmitterTimeRxMessageTests.swift; sourceTree = ""; }; + 43F82BCD1D035D5C006F5DD7 /* SessionStartRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionStartRxMessage.swift; sourceTree = ""; }; + 43F82BCF1D035D68006F5DD7 /* SessionStopRxMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionStopRxMessage.swift; sourceTree = ""; }; + 43F82BD11D037040006F5DD7 /* SessionStopRxMessageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionStopRxMessageTests.swift; sourceTree = ""; }; + 43F82BD31D037227006F5DD7 /* SessionStartRxMessageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SessionStartRxMessageTests.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -159,9 +169,12 @@ 43CABE011C3506F100005705 /* xDripG5Tests */ = { isa = PBXGroup; children = ( - 43CABE041C3506F100005705 /* Info.plist */, 43DC87C11C8B520F005BC30D /* GlucoseRxMessageTests.swift */, + 43CABE041C3506F100005705 /* Info.plist */, 43DC87BF1C8B509B005BC30D /* NSData.swift */, + 43F82BCB1D035AA4006F5DD7 /* TransmitterTimeRxMessageTests.swift */, + 43F82BD11D037040006F5DD7 /* SessionStopRxMessageTests.swift */, + 43F82BD31D037227006F5DD7 /* SessionStartRxMessageTests.swift */, ); path = xDripG5Tests; sourceTree = ""; @@ -182,7 +195,9 @@ 43CABE1D1C350B3D00005705 /* GlucoseRxMessage.swift */, 43CABE1E1C350B3D00005705 /* GlucoseTxMessage.swift */, 43CABE1F1C350B3D00005705 /* KeepAliveTxMessage.swift */, + 43F82BCD1D035D5C006F5DD7 /* SessionStartRxMessage.swift */, 43CE7CCD1CA73C22003CC1B0 /* SessionStartTxMessage.swift */, + 43F82BCF1D035D68006F5DD7 /* SessionStopRxMessage.swift */, 43CE7CCF1CA73C57003CC1B0 /* SessionStopTxMessage.swift */, 43CABE201C350B3D00005705 /* TransmitterMessage.swift */, 43CABE211C350B3D00005705 /* TransmitterTimeRxMessage.swift */, @@ -324,6 +339,8 @@ 43CABE2B1C350B3D00005705 /* KeepAliveTxMessage.swift in Sources */, 43CABE241C350B3D00005705 /* AuthChallengeTxMessage.swift in Sources */, 43CE7CD21CA73CBC003CC1B0 /* CalibrateGlucoseTxMessage.swift in Sources */, + 43F82BD01D035D68006F5DD7 /* SessionStopRxMessage.swift in Sources */, + 43F82BCE1D035D5C006F5DD7 /* SessionStartRxMessage.swift in Sources */, 43CABE251C350B3D00005705 /* AuthRequestTxMessage.swift in Sources */, 430D64C51CB7846A00FCA750 /* NSData+CRC.swift in Sources */, ); @@ -333,7 +350,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 43F82BCC1D035AA4006F5DD7 /* TransmitterTimeRxMessageTests.swift in Sources */, + 43F82BD41D037227006F5DD7 /* SessionStartRxMessageTests.swift in Sources */, 43DC87C01C8B509B005BC30D /* NSData.swift in Sources */, + 43F82BD21D037040006F5DD7 /* SessionStopRxMessageTests.swift in Sources */, 43DC87C21C8B520F005BC30D /* GlucoseRxMessageTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/xDripG5/Messages/SessionStartRxMessage.swift b/xDripG5/Messages/SessionStartRxMessage.swift new file mode 100644 index 00000000..89abd3db --- /dev/null +++ b/xDripG5/Messages/SessionStartRxMessage.swift @@ -0,0 +1,38 @@ +// +// SessionStartRxMessage.swift +// xDripG5 +// +// Created by Nathan Racklyeft on 6/4/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import Foundation + + +struct SessionStartRxMessage { + static let opcode: UInt8 = 0x27 + let status: TransmitterStatus + let received: UInt8 + + // I've only seen examples of these 2 values matching + let requestedStartTime: UInt32 + let sessionStartTime: UInt32 + + let transmitterTime: UInt32 + + init?(data: NSData) { + guard data.length == 17 && data.crcValid() else { + return nil + } + + guard data[0] == self.dynamicType.opcode else { + return nil + } + + status = TransmitterStatus(rawValue: data[1]) + received = data[2] + requestedStartTime = data[3...6] + sessionStartTime = data[7...10] + transmitterTime = data[11...14] + } +} diff --git a/xDripG5/Messages/SessionStartTxMessage.swift b/xDripG5/Messages/SessionStartTxMessage.swift index 61bb6f06..05101a90 100644 --- a/xDripG5/Messages/SessionStartTxMessage.swift +++ b/xDripG5/Messages/SessionStartTxMessage.swift @@ -9,6 +9,11 @@ import Foundation -struct SessionStartTxMessage { +struct SessionStartTxMessage: TransmitterTxMessage { let opcode: UInt8 = 0x26 + let startTime: UInt32 + + var byteSequence: [Any] { + return [opcode, startTime] + } } diff --git a/xDripG5/Messages/SessionStopRxMessage.swift b/xDripG5/Messages/SessionStopRxMessage.swift new file mode 100644 index 00000000..a0a484f1 --- /dev/null +++ b/xDripG5/Messages/SessionStopRxMessage.swift @@ -0,0 +1,35 @@ +// +// SessionStopRxMessage.swift +// xDripG5 +// +// Created by Nathan Racklyeft on 6/4/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import Foundation + + +struct SessionStopRxMessage { + static let opcode: UInt8 = 0x29 + let status: TransmitterStatus + let received: UInt8 + let sessionStopTime: UInt32 + let sessionStartTime: UInt32 + let transmitterTime: UInt32 + + init?(data: NSData) { + guard data.length == 17 && data.crcValid() else { + return nil + } + + guard data[0] == self.dynamicType.opcode else { + return nil + } + + status = TransmitterStatus(rawValue: data[1]) + received = data[2] + sessionStopTime = data[3...6] + sessionStartTime = data[7...10] + transmitterTime = data[11...14] + } +} diff --git a/xDripG5/Messages/SessionStopTxMessage.swift b/xDripG5/Messages/SessionStopTxMessage.swift index 7cd4c91b..8b4526b7 100644 --- a/xDripG5/Messages/SessionStopTxMessage.swift +++ b/xDripG5/Messages/SessionStopTxMessage.swift @@ -9,6 +9,11 @@ import Foundation -struct SessionStopTxMessage { +struct SessionStopTxMessage: TransmitterTxMessage { let opcode: UInt8 = 0x28 + let stopTime: UInt32 + + var byteSequence: [Any] { + return [opcode, stopTime] + } } diff --git a/xDripG5/Messages/TransmitterTimeRxMessage.swift b/xDripG5/Messages/TransmitterTimeRxMessage.swift index 24ba0a4d..5b5c43b2 100644 --- a/xDripG5/Messages/TransmitterTimeRxMessage.swift +++ b/xDripG5/Messages/TransmitterTimeRxMessage.swift @@ -16,16 +16,16 @@ struct TransmitterTimeRxMessage: TransmitterRxMessage { let sessionStartTime: UInt32 init?(data: NSData) { - if data.length == 16 && data.crcValid() { - if data[0] == self.dynamicType.opcode { - status = TransmitterStatus(rawValue: data[1]) - currentTime = data[2...5] - sessionStartTime = data[6...9] - } else { - return nil - } - } else { + guard data.length == 16 && data.crcValid() else { return nil } + + guard data[0] == self.dynamicType.opcode else { + return nil + } + + status = TransmitterStatus(rawValue: data[1]) + currentTime = data[2...5] + sessionStartTime = data[6...9] } } \ No newline at end of file diff --git a/xDripG5Tests/SessionStartRxMessageTests.swift b/xDripG5Tests/SessionStartRxMessageTests.swift new file mode 100644 index 00000000..fdecce80 --- /dev/null +++ b/xDripG5Tests/SessionStartRxMessageTests.swift @@ -0,0 +1,44 @@ +// +// SessionStartRxMessageTests.swift +// xDripG5 +// +// Created by Nathan Racklyeft on 6/4/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import XCTest +@testable import xDripG5 + +/// Thanks to https://github.com/mthatcher for the fixtures! +class SessionStartRxMessageTests: XCTestCase { + + func testSuccessfulStart() { + var data = NSData(hexadecimalString: "2700014bf871004bf87100e9f8710095d9")! + var message = SessionStartRxMessage(data: data)! + + XCTAssertEqual(TransmitterStatus.OK, message.status) + XCTAssertEqual(1, message.received) + XCTAssertEqual(7469131, message.requestedStartTime) + XCTAssertEqual(7469131, message.sessionStartTime) + XCTAssertEqual(7469289, message.transmitterTime) + + data = NSData(hexadecimalString: "2700012bfd71002bfd710096fd71000f6a")! + message = SessionStartRxMessage(data: data)! + + XCTAssertEqual(TransmitterStatus.OK, message.status) + XCTAssertEqual(1, message.received) + XCTAssertEqual(7470379, message.requestedStartTime) + XCTAssertEqual(7470379, message.sessionStartTime) + XCTAssertEqual(7470486, message.transmitterTime) + + data = NSData(hexadecimalString: "2700017cff71007cff7100eeff7100aeed")! + message = SessionStartRxMessage(data: data)! + + XCTAssertEqual(TransmitterStatus.OK, message.status) + XCTAssertEqual(1, message.received) + XCTAssertEqual(7470972, message.requestedStartTime) + XCTAssertEqual(7470972, message.sessionStartTime) + XCTAssertEqual(7471086, message.transmitterTime) + } + +} diff --git a/xDripG5Tests/SessionStopRxMessageTests.swift b/xDripG5Tests/SessionStopRxMessageTests.swift new file mode 100644 index 00000000..77495019 --- /dev/null +++ b/xDripG5Tests/SessionStopRxMessageTests.swift @@ -0,0 +1,44 @@ +// +// SessionStopRxMessageTests.swift +// xDripG5 +// +// Created by Nathan Racklyeft on 6/4/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import XCTest +@testable import xDripG5 + +/// Thanks to https://github.com/mthatcher for the fixtures! +class SessionStopRxMessageTests: XCTestCase { + + func testSuccessfulStop() { + var data = NSData(hexadecimalString: "29000128027200ffffffff47027200ba85")! + var message = SessionStopRxMessage(data: data)! + + XCTAssertEqual(TransmitterStatus.OK, message.status) + XCTAssertEqual(1, message.received) + XCTAssertEqual(7471656, message.sessionStopTime) + XCTAssertEqual(0xffffffff, message.sessionStartTime) + XCTAssertEqual(7471687, message.transmitterTime) + + data = NSData(hexadecimalString: "2900013ffe7100ffffffffc2fe71008268")! + message = SessionStopRxMessage(data: data)! + + XCTAssertEqual(TransmitterStatus.OK, message.status) + XCTAssertEqual(1, message.received) + XCTAssertEqual(7470655, message.sessionStopTime) + XCTAssertEqual(0xffffffff, message.sessionStartTime) + XCTAssertEqual(7470786, message.transmitterTime) + + data = NSData(hexadecimalString: "290001f5fb7100ffffffff6afc7100fa8a")! + message = SessionStopRxMessage(data: data)! + + XCTAssertEqual(TransmitterStatus.OK, message.status) + XCTAssertEqual(1, message.received) + XCTAssertEqual(7470069, message.sessionStopTime) + XCTAssertEqual(0xffffffff, message.sessionStartTime) + XCTAssertEqual(7470186, message.transmitterTime) + } + +} diff --git a/xDripG5Tests/TransmitterTimeRxMessageTests.swift b/xDripG5Tests/TransmitterTimeRxMessageTests.swift new file mode 100644 index 00000000..b1bf22dc --- /dev/null +++ b/xDripG5Tests/TransmitterTimeRxMessageTests.swift @@ -0,0 +1,47 @@ +// +// TransmitterTimeRxMessageTests.swift +// xDripG5 +// +// Created by Nathan Racklyeft on 6/4/16. +// Copyright © 2016 Nathan Racklyeft. All rights reserved. +// + +import XCTest +@testable import xDripG5 + +/// Thanks to https://github.com/mthatcher for the fixtures! +class TransmitterTimeRxMessageTests: XCTestCase { + + func testNoSession() { + var data = NSData(hexadecimalString: "2500e8f87100ffffffff010000000a70")! + var message = TransmitterTimeRxMessage(data: data)! + + XCTAssertEqual(TransmitterStatus.OK, message.status) + XCTAssertEqual(7469288, message.currentTime) + XCTAssertEqual(0xffffffff, message.sessionStartTime) + + data = NSData(hexadecimalString: "250096fd7100ffffffff01000000226d")! + message = TransmitterTimeRxMessage(data: data)! + + XCTAssertEqual(TransmitterStatus.OK, message.status) + XCTAssertEqual(7470486, message.currentTime) + XCTAssertEqual(0xffffffff, message.sessionStartTime) + + data = NSData(hexadecimalString: "2500eeff7100ffffffff010000008952")! + message = TransmitterTimeRxMessage(data: data)! + + XCTAssertEqual(TransmitterStatus.OK, message.status) + XCTAssertEqual(7471086, message.currentTime) + XCTAssertEqual(0xffffffff, message.sessionStartTime) + } + + func testInSession() { + let data = NSData(hexadecimalString: "2500470272007cff710001000000fa1d")! + let message = TransmitterTimeRxMessage(data: data)! + + XCTAssertEqual(TransmitterStatus.OK, message.status) + XCTAssertEqual(7471687, message.currentTime) + XCTAssertEqual(7470972, message.sessionStartTime) + + } +}