From 4a080042c596579466429766b4a025f63c2424f3 Mon Sep 17 00:00:00 2001 From: Alsey Coleman Miller Date: Thu, 30 Nov 2017 02:07:51 -0500 Subject: [PATCH] Fixed event parsing --- Sources/HCIGeneralEventParameter.swift | 11 ++--- Sources/LowEnergyEventParameter.swift | 14 ++---- Tests/BluetoothTests/BluetoothTests.swift | 56 +++++++++++++++++++++-- 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/Sources/HCIGeneralEventParameter.swift b/Sources/HCIGeneralEventParameter.swift index bdbb46258..84f580974 100644 --- a/Sources/HCIGeneralEventParameter.swift +++ b/Sources/HCIGeneralEventParameter.swift @@ -88,17 +88,16 @@ public extension HCIGeneralEvent { public static let event = HCIGeneralEvent.LowEnergyMeta public static let length = 1 // 1 ... HCI.maximumEventSize - public var subevent: UInt8 = 0 - public var data = [UInt8]() - - public init() { } + public let subevent: LowEnergyEvent + public let data: [UInt8] public init?(byteValue: [UInt8]) { - guard byteValue.count >= LowEnergyMetaParameter.length + guard byteValue.count >= LowEnergyMetaParameter.length, + let subevent = LowEnergyEvent(rawValue: byteValue[0]) else { return nil } - self.subevent = byteValue[0] + self.subevent = subevent if byteValue.count > 1 { diff --git a/Sources/LowEnergyEventParameter.swift b/Sources/LowEnergyEventParameter.swift index a1a7897dd..42933f6d0 100644 --- a/Sources/LowEnergyEventParameter.swift +++ b/Sources/LowEnergyEventParameter.swift @@ -117,8 +117,6 @@ public extension LowEnergyEvent { guard let status = Status(rawValue: statusByte), let role = Role(rawValue: roleByte), let peerAddressType = LowEnergyAddressType(rawValue: peerAddressTypeByte), - let interval = ConnectionInterval(rawValue: intervalRawValue), - let latency = ConnectionInterval(rawValue: latencyRawValue), let supervisionTimeout = SupervisionTimeout(rawValue: supervisionTimeoutRaw), let masterClockAccuracy = MasterClockAccuracy(rawValue: masterClockAccuracyByte) else { return nil } @@ -128,8 +126,8 @@ public extension LowEnergyEvent { self.role = role self.peerAddressType = peerAddressType self.peerAddress = peerAddress - self.interval = interval - self.latency = latency + self.interval = ConnectionInterval(rawValue: intervalRawValue) + self.latency = ConnectionInterval(rawValue: latencyRawValue) self.supervisionTimeout = supervisionTimeout self.masterClockAccuracy = masterClockAccuracy } @@ -159,13 +157,7 @@ public extension LowEnergyEvent { public let rawValue: UInt16 - public init?(rawValue: UInt16) { - - guard rawValue >= ConnectionInterval.min.rawValue, - rawValue <= ConnectionInterval.max.rawValue - else { return nil } - - assert((ConnectionInterval.min.rawValue ... ConnectionInterval.max.rawValue).contains(rawValue)) + public init(rawValue: UInt16) { self.rawValue = rawValue } diff --git a/Tests/BluetoothTests/BluetoothTests.swift b/Tests/BluetoothTests/BluetoothTests.swift index 490fcd248..ce754f5fe 100755 --- a/Tests/BluetoothTests/BluetoothTests.swift +++ b/Tests/BluetoothTests/BluetoothTests.swift @@ -15,7 +15,8 @@ final class BluetoothTests: XCTestCase { static let allTests = [ ("testAddress", testAddress), ("testParseAdvertisingReportData", testParseAdvertisingReportData), - ("testCommandStatusEvent", testCommandStatusEvent) + ("testCommandStatusEvent", testCommandStatusEvent), + ("testLEConnection", testLEConnection) ] func testAddress() { @@ -39,11 +40,10 @@ final class BluetoothTests: XCTestCase { let eventData = Array(data[3 ..< readBytes]) - guard let meta = HCIGeneralEvent.LowEnergyMetaParameter(byteValue: eventData), - let lowEnergyEvent = LowEnergyEvent(rawValue: meta.subevent) + guard let meta = HCIGeneralEvent.LowEnergyMetaParameter(byteValue: eventData) else { XCTFail("Could not parse"); return [] } - XCTAssert(lowEnergyEvent == .advertisingReport, "Invalid event type \(lowEnergyEvent)") + XCTAssert(meta.subevent == .advertisingReport, "Invalid event type \(meta.subevent)") guard let advertisingReport = LowEnergyEvent.AdvertisingReportEventParameter(byteValue: meta.data) else { XCTFail("Could not parse"); return [] } @@ -100,6 +100,54 @@ final class BluetoothTests: XCTestCase { XCTAssert(event.status == HCIError.aclConnectionExists.rawValue) } } + + func testLEConnection() { + + do { + + let readBytes = 7 + let data: [UInt8] = [4, 15, 4, 0, 1, 13, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + + guard let event: HCIGeneralEvent.CommandStatusParameter = parseEvent(readBytes, data) + else { XCTFail("Could not parse"); return } + + XCTAssert(event.status == 0x00) + } + + do { + + let readBytes = 22 + let data: [UInt8] = [4, 62, 19, 1, 0, 71, 0, 0, 0, 66, 103, 166, 50, 188, 172, 15, 0, 0, 0, 128, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + + guard let metaEvent: HCIGeneralEvent.LowEnergyMetaParameter = parseEvent(readBytes, data) + else { XCTFail("Could not parse"); return } + + XCTAssert(metaEvent.subevent == .connectionComplete) + + guard let event = LowEnergyEvent.ConnectionCompleteParameter(byteValue: metaEvent.data) + else { XCTFail("Could not parse"); return } + + XCTAssert(event.status == .success) + + print("Connection handle: ", event.handle) + } + } +} + +internal func parseEvent (_ actualBytesRead: Int, _ eventBuffer: [UInt8]) -> T? { + + let headerData = Array(eventBuffer[1 ..< 1 + HCIEventHeader.length]) + let eventData = Array(eventBuffer[(1 + HCIEventHeader.length) ..< actualBytesRead]) + + guard let eventHeader = HCIEventHeader(bytes: headerData) + else { return nil } + + XCTAssert(eventHeader.event == T.event.rawValue) + + guard let event = T(byteValue: eventData) + else { return nil } + + return event } /// HCI Event Packet Header