Skip to content

Commit

Permalink
Added HCICommandTimeout
Browse files Browse the repository at this point in the history
  • Loading branch information
colemancda committed Mar 31, 2018
1 parent 1fcebe0 commit b92ffcb
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 44 deletions.
20 changes: 10 additions & 10 deletions Sources/BluetoothHostController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,30 @@ public protocol BluetoothHostControllerInterface {
var address: Address { get }

/// Send an HCI command to the controller.
func deviceCommand <T: HCICommand> (_ command: T) throws
func deviceCommand <C: HCICommand> (_ command: C) throws

/// Send an HCI command with parameters to the controller.
func deviceCommand <T: HCICommandParameter> (_ commandParameter: T) throws
func deviceCommand <CP: HCICommandParameter> (_ commandParameter: CP) throws

/// Send a command to the controller and wait for response.
func deviceRequest<C: HCICommand>(_ command: C, timeout: Int) throws
func deviceRequest<C: HCICommand>(_ command: C, timeout: HCICommandTimeout) throws

/// Send a command to the controller and wait for response.
func deviceRequest<CP: HCICommandParameter>(_ commandParameter: CP, timeout: Int) throws
func deviceRequest<CP: HCICommandParameter>(_ commandParameter: CP, timeout: HCICommandTimeout) throws

/// Sends a command to the device and waits for a response.
func deviceRequest <CP: HCICommandParameter, EP: HCIEventParameter> (_ commandParameter: CP, _ eventParameterType: EP.Type, timeout: Int) throws -> EP
func deviceRequest <CP: HCICommandParameter, EP: HCIEventParameter> (_ commandParameter: CP, _ eventParameterType: EP.Type, timeout: HCICommandTimeout) throws -> EP

/// Sends a command to the device and waits for a response with return parameter values.
func deviceRequest <Return: HCICommandReturnParameter> (_ commandReturnType : Return.Type, timeout: Int) throws -> Return
func deviceRequest <Return: HCICommandReturnParameter> (_ commandReturnType : Return.Type, timeout: HCICommandTimeout) throws -> Return

/// Sends a command to the device and waits for a response with return parameter values.
func deviceRequest <CP: HCICommandParameter, Return: HCICommandReturnParameter> (_ commandParameter: CP, _ commandReturnType: Return.Type, timeout: Int) throws -> Return
func deviceRequest <CP: HCICommandParameter, Return: HCICommandReturnParameter> (_ commandParameter: CP, _ commandReturnType: Return.Type, timeout: HCICommandTimeout) throws -> Return

/// Polls and waits for events.
func pollEvent <T: HCIEventParameter> (_ eventParameterType: T.Type,
shouldContinue: () -> (Bool),
event: (T) throws -> ()) throws
func pollEvent <EP: HCIEventParameter> (_ eventParameterType: EP.Type,
shouldContinue: () -> (Bool),
event: (EP) throws -> ()) throws
}

/// Bluetooth HCI errors
Expand Down
5 changes: 1 addition & 4 deletions Sources/HCI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,7 @@ public struct HCI {
public static let maximumNameLength = 248

public static let typeLength = 1

/// Default timeout of HCI commands in miliseconds.
public static let defaultTimeout = 1000


// MARK: - Typealiases

public typealias OpcodeGroupField = HCIOpcodeGroupField
Expand Down
72 changes: 72 additions & 0 deletions Sources/HCICommandTimeout.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// HCICommandTimeout.swift
// Bluetooth
//
// Created by Alsey Coleman Miller on 3/31/18.
// Copyright © 2018 PureSwift. All rights reserved.
//

import Foundation

/// The duration of an HCI command.
public struct HCICommandTimeout: RawRepresentable {

/// The duration of the timeout in miliseconds.
public var rawValue: UInt

public init(rawValue: UInt) {
self.rawValue = rawValue
}

/// Default timeout of HCI commands in miliseconds.
public static let `default`: HCICommandTimeout = 1000
}

public extension HCICommandTimeout {

/// Duration in seconds.
var duration: TimeInterval {

return TimeInterval(rawValue) / 1000.0
}
}

// MARK: - ExpressibleByIntegerLiteral

extension HCICommandTimeout: ExpressibleByIntegerLiteral {

public init(integerLiteral value: UInt) {

self.rawValue = value
}
}

// MARK: - Equatable

extension HCICommandTimeout: Equatable {

public static func == (lhs: HCICommandTimeout, rhs: HCICommandTimeout) -> Bool {

return lhs.rawValue == rhs.rawValue
}
}

// MARK: - Hashable

extension HCICommandTimeout: Hashable {

public var hashValue: Int {

return rawValue.hashValue
}
}

// MARK: - CustomStringConvertible

extension HCICommandTimeout: CustomStringConvertible {

public var description: String {

return "\(duration) seconds"
}
}
4 changes: 2 additions & 2 deletions Sources/HostControllerLocalName.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public extension BluetoothHostControllerInterface {
/// Read Local Name Command
///
/// Provides the ability to read the stored user- friendly name for the BR/EDR Controller.
func writeLocalName(_ newValue: String, timeout: Int = HCI.defaultTimeout) throws {
func writeLocalName(_ newValue: String, timeout: HCICommandTimeout = .default) throws {

guard let command = HostControllerBasebandCommand.WriteLocalNameParameter(localName: newValue)
else { fatalError("") }
Expand All @@ -24,7 +24,7 @@ public extension BluetoothHostControllerInterface {
/// Write Local Name Command
///
/// Provides the ability to modify the user- friendly name for the BR/EDR Controller.
func readLocalName(timeout: Int = HCI.defaultTimeout) throws -> String {
func readLocalName(timeout: HCICommandTimeout = .default) throws -> String {

let value = try deviceRequest(HostControllerBasebandCommand.ReadLocalNameReturnParameter.self,
timeout: timeout)
Expand Down
6 changes: 3 additions & 3 deletions Sources/LowEnergyAdvertising.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ import Foundation

public extension BluetoothHostControllerInterface {

func enableLowEnergyAdvertising(_ enabled: Bool = true, timeout: Int = HCI.defaultTimeout) throws {
func enableLowEnergyAdvertising(_ enabled: Bool = true, timeout: HCICommandTimeout = .default) throws {

let parameter = LowEnergyCommand.SetAdvertiseEnableParameter(enabled: enabled)

try deviceRequest(parameter, timeout: timeout)
}

func setLowEnergyAdvertisingData(_ data: LowEnergyResponseData, length: UInt8, timeout: Int = HCI.defaultTimeout) throws {
func setLowEnergyAdvertisingData(_ data: LowEnergyResponseData, length: UInt8, timeout: HCICommandTimeout = .default) throws {

let parameter = LowEnergyCommand.SetAdvertisingDataParameter(data: data, length: length)

try deviceRequest(parameter, timeout: timeout)
}

func setLowEnergyAdvertisingData(data: Data, timeout: Int = HCI.defaultTimeout) throws {
func setLowEnergyAdvertisingData(data: Data, timeout: HCICommandTimeout = .default) throws {

precondition(data.count <= 31, "LE Advertising Data can only be 31 octets")

Expand Down
2 changes: 1 addition & 1 deletion Sources/LowEnergyChannelMap.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public extension BluetoothHostControllerInterface {
/// Returns the current Channel_Map for the specified Connection_Handle. The returned value indicates the state
/// of the Channel_Map specified by the last transmitted or received Channel_Map (in a CONNECT_IND or LL_CHANNEL_MAP_IND message)
/// for the specified Connection_Handle, regardless of whether the Master has received an acknowledgment.
func lowEnergyReadChannelMap(handle: UInt16, commandTimeout timeout: Int = HCI.defaultTimeout) throws -> LowEnergyChannelMap {
func lowEnergyReadChannelMap(handle: UInt16, timeout: HCICommandTimeout = .default) throws -> LowEnergyChannelMap {

let parameters = LowEnergyCommand.ReadChannelMapParameter(connectionHandle: handle)

Expand Down
10 changes: 5 additions & 5 deletions Sources/LowEnergyConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ public extension BluetoothHostControllerInterface {
func lowEnergyCreateConnection(address peerAddress: Address,
type peerAddressType: LowEnergyAddressType = .public,
ownAddressType: LowEnergyAddressType = .public,
commandTimeout timeout: Int = HCI.defaultTimeout) throws -> UInt16 {
timeout: HCICommandTimeout = .default) throws -> UInt16 {

let parameters = LowEnergyCommand.CreateConnectionParameter(peerAddressType: peerAddressType,
peerAddress: peerAddress,
ownAddressType: ownAddressType)

return try lowEnergyCreateConnection(parameters: parameters, commandTimeout: timeout)
return try lowEnergyCreateConnection(parameters: parameters, timeout: timeout)
}

func lowEnergyCreateConnection(parameters: LowEnergyCommand.CreateConnectionParameter,
commandTimeout timeout: Int = HCI.defaultTimeout) throws -> UInt16 {
timeout: HCICommandTimeout = .default) throws -> UInt16 {

// connect with specified parameters
let event = try deviceRequest(parameters,
Expand All @@ -44,7 +44,7 @@ public extension BluetoothHostControllerInterface {
/// This command shall only be issued after the LE_Create_Connection command has been issued,
/// a Command Status event has been received for the LE Create Connection command and before
/// the LE Connection Complete event.
func lowEnergyCreateConnectionCancel(commandTimeout timeout: Int = HCI.defaultTimeout) throws {
func lowEnergyCreateConnectionCancel(timeout: HCICommandTimeout = .default) throws {

// cancel connection
try deviceRequest(LowEnergyCommand.createConnectionCancel, timeout: timeout)
Expand All @@ -55,7 +55,7 @@ public extension BluetoothHostControllerInterface {
connectionLatency: LowEnergyConnectionLatency = .zero,
supervisionTimeout: LowEnergySupervisionTimeout = .max,
connectionLength: LowEnergyConnectionLength = .full,
commandTimeout timeout: Int = HCI.defaultTimeout) throws {
timeout: HCICommandTimeout = .default) throws {

let parameters = LowEnergyCommand.UpdateConnectionParameter(connectionHandle: handle,
connectionInterval: connectionInterval,
Expand Down
4 changes: 2 additions & 2 deletions Sources/LowEnergyEncryption.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public extension BluetoothHostControllerInterface {
///
/// The Commnad is used to request the Controller to encrypt the Plaintext_Data in the command using the Key given in the command
/// and returns the Encrypted_Data to the Host.
func lowEnergyEncrypt(key: UInt128, data: UInt128, commandTimeout timeout: Int = HCI.defaultTimeout) throws -> UInt128 {
func lowEnergyEncrypt(key: UInt128, data: UInt128, timeout: HCICommandTimeout = .default) throws -> UInt128 {

let parameters = LowEnergyCommand.EncryptParameter(key: key, data: data)

Expand All @@ -26,7 +26,7 @@ public extension BluetoothHostControllerInterface {
/// LE Rand Command
///
/// The command is used to request the Controller to generate 8 octets of random data to be sent to the Host.
func lowEnergyRandom(commandTimeout timeout: Int = HCI.defaultTimeout) throws -> UInt64 {
func lowEnergyRandom(timeout: HCICommandTimeout = .default) throws -> UInt64 {

let returnParameters = try deviceRequest(LowEnergyCommand.RandomReturnParameter.self, timeout: timeout)

Expand Down
14 changes: 7 additions & 7 deletions Sources/LowEnergyScan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public extension BluetoothHostControllerInterface {
/// Scan LE devices.
func lowEnergyScan(filterDuplicates: Bool = true,
parameters: LowEnergyCommand.SetScanParametersParameter = .init(),
commandTimeout timeout: Int = HCI.defaultTimeout,
timeout: HCICommandTimeout = .default,
shouldContinue: () -> (Bool),
foundDevice: (LowEnergyScannedDevice) -> ()) throws {

Expand Down Expand Up @@ -62,7 +62,7 @@ public extension BluetoothHostControllerInterface {
func lowEnergyScan(duration: TimeInterval = 10,
filterDuplicates: Bool = true,
parameters: LowEnergyCommand.SetScanParametersParameter = .init(),
commandTimeout timeout: Int = HCI.defaultTimeout) throws -> [LowEnergyScannedDevice] {
timeout: HCICommandTimeout = .default) throws -> [LowEnergyScannedDevice] {

let startDate = Date()
let endDate = startDate + duration
Expand All @@ -71,7 +71,7 @@ public extension BluetoothHostControllerInterface {

try lowEnergyScan(filterDuplicates: filterDuplicates,
parameters: parameters,
commandTimeout: timeout,
timeout: timeout,
shouldContinue: { Date() < endDate },
foundDevice: { foundDevices.append($0) })

Expand All @@ -88,7 +88,7 @@ public extension BluetoothHostControllerInterface {
/// - Parameter commandTimeout: The timeout to use for each HCI command.
///
/// - Precondition: The provided length must be less than or equal to 31.
func setLowEnergyScanResponse(_ data: LowEnergyResponseData, length: UInt8, commandTimeout: Int = HCI.defaultTimeout) throws {
func setLowEnergyScanResponse(_ data: LowEnergyResponseData, length: UInt8, timeout: HCICommandTimeout = .default) throws {

precondition(length <= 31, "LE Scan Response Data can only be 31 octets")

Expand All @@ -97,7 +97,7 @@ public extension BluetoothHostControllerInterface {

//print("Setting Scan Response Data")

try deviceRequest(setScanResponseDataCommand, timeout: commandTimeout)
try deviceRequest(setScanResponseDataCommand, timeout: timeout)
}

/// Set the LE Scan Response
Expand All @@ -111,12 +111,12 @@ public extension BluetoothHostControllerInterface {
/// - Parameter commandTimeout: The timeout to use for each HCI command.
///
/// - Precondition: The provided length must be less than or equal to 31.
func setLowEnergyScanResponse(_ data: Data, commandTimeout: Int = HCI.defaultTimeout) throws {
func setLowEnergyScanResponse(_ data: Data, timeout: HCICommandTimeout = .default) throws {

precondition(data.count <= 31, "LE Scan Response Data can only be 31 octets")

let bytes: LowEnergyResponseData = (data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], data[28], data[29], data[30])

try setLowEnergyScanResponse(bytes, length: UInt8(data.count), commandTimeout: commandTimeout)
try setLowEnergyScanResponse(bytes, length: UInt8(data.count), timeout: timeout)
}
}
8 changes: 4 additions & 4 deletions Sources/LowEnergyWhiteList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public extension BluetoothHostControllerInterface {
/// LE Read White List Size Command
///
/// Used to read the total number of white list entries that can be stored in the Controller.
func lowEnergyReadWhiteListSize(commandTimeout timeout: Int = HCI.defaultTimeout) throws -> Int {
func lowEnergyReadWhiteListSize(timeout: HCICommandTimeout = .default) throws -> Int {

let sizeReturnParameter = try deviceRequest(LowEnergyCommand.ReadWhiteListSizeReturnParameter.self, timeout: timeout)

Expand All @@ -21,7 +21,7 @@ public extension BluetoothHostControllerInterface {
/// LE Clear White List Command
///
/// Used to clear the White List stored in the Controller.
func lowEnergyClearWhiteList(commandTimeout timeout: Int = HCI.defaultTimeout) throws {
func lowEnergyClearWhiteList(timeout: HCICommandTimeout = .default) throws {

// clear white list
try deviceRequest(LowEnergyCommand.clearWhiteList, timeout: timeout)
Expand All @@ -30,15 +30,15 @@ public extension BluetoothHostControllerInterface {
/// LE Add Device To White List Command
///
/// Used to add a single device to the White List stored in the Controller.
func lowEnergyAddDeviceToWhiteList(whiteListDevice: LowEnergyWhiteListDevice ,commandTimeout timeout: Int = HCI.defaultTimeout) throws {
func lowEnergyAddDeviceToWhiteList(whiteListDevice: LowEnergyWhiteListDevice ,timeout: HCICommandTimeout = .default) throws {

try deviceRequest(LowEnergyCommand.AddDeviceToWhiteListParameter(device: whiteListDevice), timeout: timeout)
}

/// LE Remove Device From White List Command
///
/// Used to remove a single device from the White List stored in the Controller.
func lowEnergyRemoveDeviceToWhiteList(whiteListDevice: LowEnergyWhiteListDevice ,commandTimeout timeout: Int = HCI.defaultTimeout) throws {
func lowEnergyRemoveDeviceToWhiteList(whiteListDevice: LowEnergyWhiteListDevice ,timeout: HCICommandTimeout = .default) throws {

try deviceRequest(LowEnergyCommand.RemoveDeviceToWhiteListParameter(device: whiteListDevice), timeout: timeout)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/iBeacon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public extension BluetoothHostControllerInterface {
minor: UInt16,
rssi: Int8,
interval: UInt16 = 100,
timeout: Int = HCI.defaultTimeout) throws {
timeout: HCICommandTimeout = .default) throws {

// set advertising parameters
let advertisingParameters = LowEnergyCommand.SetAdvertisingParametersParameter(interval: (interval, interval))
Expand Down
Loading

0 comments on commit b92ffcb

Please sign in to comment.