Skip to content

Commit

Permalink
feature/29-connection-state - Expose Connection state
Browse files Browse the repository at this point in the history
- Exposed a connection state
- Added a simple change handler for now
  • Loading branch information
sureshjoshi authored May 19, 2020
1 parent 06dfdc7 commit 8f1a489
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 43 deletions.
15 changes: 15 additions & 0 deletions Sources/SwiftyTeeth/ConnectionState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// ConnectionState.swift
// SwiftyTeeth
//
// Created by SJ on 2020-05-18.
//

import Foundation

public enum ConnectionState {
case connecting
case connected
case disconnecting
case disconnected
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,8 @@ import Foundation
import CoreBluetooth

public typealias DiscoveredCharacteristic = (service: Service, characteristics: [Characteristic])

public typealias ConnectionHandler = ((Bool) -> Void)
public typealias ServiceDiscovery = ((Result<[Service], Error>) -> Void)
public typealias CharacteristicDiscovery = ((Result<DiscoveredCharacteristic, Error>) -> Void)
//public typealias ReadHandler = ((Result<Data>) -> Void)
//public typealias WriteHandler = ((Result<Void>) -> Void)

public enum ConnectionError: Error {
case disconnected
Expand All @@ -30,12 +26,18 @@ open class Device: NSObject {
fileprivate let tag = "SwiftyDevice"

let peripheral: CBPeripheral

var discoveredServices = [UUID: Service]()

private let manager: SwiftyTeeth

private var connectionHandler: ConnectionHandler?
public var connectionStateChangedHandler: ((ConnectionState) -> Void)? {
didSet {
// TODO: Replace this with an observing property on peripheral.state
connectionStateChangedHandler?(connectionState)
}
}

private var connectionHandler: ((ConnectionState) -> Void)?
private var notificationHandler = [CBCharacteristic: ((Result<Data, Error>) -> Void)]()

// Connection parameters
Expand All @@ -60,8 +62,23 @@ open class Device: NSObject {

// MARK: Computed properties
extension Device {
open var connectionState: ConnectionState {
switch peripheral.state {
case .connecting:
return .connecting
case .connected:
return .connected
case .disconnecting:
return .disconnecting
case .disconnected:
return .disconnected
@unknown default:
return .disconnected
}
}

open var isConnected: Bool {
return peripheral.state == .connected
return connectionState == .connected
}

open var name: String {
Expand All @@ -72,11 +89,6 @@ extension Device {
return peripheral.identifier.uuidString
}

// open var connectionState: StateEnumOfSomeSort {
// return peripheral.state
// }


// open var rssi: Int {
// return peripheral.
// }
Expand All @@ -86,8 +98,9 @@ extension Device {
extension Device {
// Annoyingly, iOS has the connection functionality sitting on the central manager, instead of on the peripheral
// TODO: Should the completion be optional?
open func connect(with timeout: TimeInterval? = nil, autoReconnect: Bool = true, complete: ConnectionHandler?) {
open func connect(with timeout: TimeInterval? = nil, autoReconnect: Bool = true, complete: ((ConnectionState) -> Void)?) {
Log(v: "Calling connect", tag: tag)
connectionStateChangedHandler?(.connecting)
self.connectionHandler = complete
self.autoReconnect = autoReconnect
self.manager.connect(to: self)
Expand All @@ -97,6 +110,7 @@ extension Device {
open func disconnect(autoReconnect: Bool = false) {
// Disable auto reconnection when calling the disconnect API
Log(v: "Calling disconnect", tag: tag)
connectionStateChangedHandler?(.disconnecting)
self.autoReconnect = autoReconnect
self.manager.disconnect(from: self)
}
Expand Down Expand Up @@ -272,12 +286,14 @@ internal extension Device {

func didConnect() {
Log(v: "didConnect: Calling connection handler: Is handler nil? \(connectionHandler == nil)", tag: tag)
connectionHandler?(true)
connectionHandler?(.connected)
connectionStateChangedHandler?(.connected)
}

func didDisconnect() {
Log(v: "didDisconnect: Calling disconnection handler: Is handler nil? \(connectionHandler == nil)", tag: tag)
connectionHandler?(false)
connectionHandler?(.disconnected)
connectionStateChangedHandler?(.disconnected)
if autoReconnect == true {
connect(complete: connectionHandler)
}
Expand Down
File renamed without changes.
File renamed without changes.
9 changes: 6 additions & 3 deletions SwiftyTeeth Sample/UI/PeripheralView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ final class PeripheralViewModel: ObservableObject {

init(peripheral: Device) {
self.peripheral = peripheral
peripheral.connectionStateChangedHandler = { state in
self.log("Connection state is \(state)")
}
}

private func log(_ text: String) {
Expand All @@ -28,13 +31,13 @@ final class PeripheralViewModel: ObservableObject {
}

func connect() {
peripheral.connect { (isConnected) in
guard isConnected == true else {
peripheral.connect { (connectionState) in
guard connectionState == .connected else {
self.log("Not connected")
return
}

self.log("App: Device is connected? \(isConnected)")
self.log("App: Device is connected? \(connectionState == .connected)")
self.log("App: Starting service discovery...")

self.peripheral.discoverServices { (result) in
Expand Down
46 changes: 21 additions & 25 deletions SwiftyTeeth.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
1952CBAA238A453E00EBBCD3 /* SwiftyToothLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1952CBA8238A451700EBBCD3 /* SwiftyToothLogger.swift */; };
195A59141E4834F0002B076A /* CBCharacterisic+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195A59121E482C4F002B076A /* CBCharacterisic+String.swift */; };
195A59151E4834F5002B076A /* CBService+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 195A59101E482BF4002B076A /* CBService+String.swift */; };
19A06869206B130F0023D5EE /* OperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A06868206B130F0023D5EE /* OperationQueue.swift */; };
19A06869206B130F0023D5EE /* OperationQueue+SwiftyQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A06868206B130F0023D5EE /* OperationQueue+SwiftyQueue.swift */; };
19A0686B206B162E0023D5EE /* SwiftyQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A0686A206B162E0023D5EE /* SwiftyQueue.swift */; };
19A0686D206B18B20023D5EE /* QueueItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A0686C206B18B20023D5EE /* QueueItem.swift */; };
19B7DC8F1F0D624F0035FDFA /* SwiftyTeethLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19B7DC8E1F0D624F0035FDFA /* SwiftyTeethLogger.swift */; };
Expand All @@ -30,6 +30,7 @@
33C3319524735BAB00D90A7A /* Characteristic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C3318B24735BAB00D90A7A /* Characteristic.swift */; };
33C3319724735C7400D90A7A /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C3319624735C7400D90A7A /* Logger.swift */; };
33C3319824735C7400D90A7A /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C3319624735C7400D90A7A /* Logger.swift */; };
33C3319B247376D400D90A7A /* ConnectionState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C3319A247376D400D90A7A /* ConnectionState.swift */; };
33FEC8B4242EF0C9001F9BD9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33FEC8B3242EF0C9001F9BD9 /* AppDelegate.swift */; };
33FEC8B6242EF0C9001F9BD9 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33FEC8B5242EF0C9001F9BD9 /* SceneDelegate.swift */; };
33FEC8B8242EF0C9001F9BD9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33FEC8B7242EF0C9001F9BD9 /* ContentView.swift */; };
Expand Down Expand Up @@ -89,7 +90,7 @@
195A59101E482BF4002B076A /* CBService+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CBService+String.swift"; sourceTree = "<group>"; };
195A59121E482C4F002B076A /* CBCharacterisic+String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CBCharacterisic+String.swift"; sourceTree = "<group>"; };
1966DC73238A29390085C9A5 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
19A06868206B130F0023D5EE /* OperationQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationQueue.swift; sourceTree = "<group>"; };
19A06868206B130F0023D5EE /* OperationQueue+SwiftyQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OperationQueue+SwiftyQueue.swift"; sourceTree = "<group>"; };
19A0686A206B162E0023D5EE /* SwiftyQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftyQueue.swift; sourceTree = "<group>"; };
19A0686C206B18B20023D5EE /* QueueItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueItem.swift; sourceTree = "<group>"; };
19B7DC8E1F0D624F0035FDFA /* SwiftyTeethLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyTeethLogger.swift; sourceTree = "<group>"; };
Expand All @@ -101,6 +102,7 @@
33C3318A24735BAB00D90A7A /* UUID+CBUUID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UUID+CBUUID.swift"; sourceTree = "<group>"; };
33C3318B24735BAB00D90A7A /* Characteristic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Characteristic.swift; sourceTree = "<group>"; };
33C3319624735C7400D90A7A /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
33C3319A247376D400D90A7A /* ConnectionState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectionState.swift; sourceTree = "<group>"; };
33C34994242C2856006C7383 /* Peripheral */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Peripheral; path = Examples/Peripheral; sourceTree = "<group>"; };
33FEC8AC242EEE54001F9BD9 /* Central */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Central; path = Examples/Central; sourceTree = "<group>"; };
33FEC8B1242EF0C9001F9BD9 /* SwiftyTeeth Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SwiftyTeeth Sample.app"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -168,13 +170,16 @@
1952CB96238A3E6B00EBBCD3 /* SwiftyTeeth */ = {
isa = PBXGroup;
children = (
33C33199247376A100D90A7A /* Internal */,
8B64D1971DC2E39900D41A2C /* Extensions */,
8B64D19A1DC2E39900D41A2C /* Models */,
8B64D19C1DC2E39900D41A2C /* Protocols */,
8B64D1CF1DC2E8FE00D41A2C /* SwiftyTeeth.swift */,
19A0686C206B18B20023D5EE /* QueueItem.swift */,
8B64D1DC1DC2F5D000D41A2C /* Device.swift */,
8B64D1E21DC2FCEB00D41A2C /* SwiftyTeethable.swift */,
19B7DC8E1F0D624F0035FDFA /* SwiftyTeethLogger.swift */,
8B64D18D1DC2E16300D41A2C /* SwiftyTeeth.h */,
8B64D1A11DC2E42000D41A2C /* Info.plist */,
33C3319A247376D400D90A7A /* ConnectionState.swift */,
);
path = SwiftyTeeth;
sourceTree = "<group>";
Expand Down Expand Up @@ -219,6 +224,14 @@
path = Extensions;
sourceTree = "<group>";
};
33C33199247376A100D90A7A /* Internal */ = {
isa = PBXGroup;
children = (
19A0686A206B162E0023D5EE /* SwiftyQueue.swift */,
);
path = Internal;
sourceTree = "<group>";
};
33FEC8B2242EF0C9001F9BD9 /* SwiftyTeeth Sample */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -316,31 +329,13 @@
8B64D1971DC2E39900D41A2C /* Extensions */ = {
isa = PBXGroup;
children = (
195A59101E482BF4002B076A /* CBService+String.swift */,
195A59121E482C4F002B076A /* CBCharacterisic+String.swift */,
19A06868206B130F0023D5EE /* OperationQueue.swift */,
195A59101E482BF4002B076A /* CBService+String.swift */,
19A06868206B130F0023D5EE /* OperationQueue+SwiftyQueue.swift */,
);
path = Extensions;
sourceTree = "<group>";
};
8B64D19A1DC2E39900D41A2C /* Models */ = {
isa = PBXGroup;
children = (
8B64D1DC1DC2F5D000D41A2C /* Device.swift */,
19A0686C206B18B20023D5EE /* QueueItem.swift */,
);
path = Models;
sourceTree = "<group>";
};
8B64D19C1DC2E39900D41A2C /* Protocols */ = {
isa = PBXGroup;
children = (
8B64D1E21DC2FCEB00D41A2C /* SwiftyTeethable.swift */,
19A0686A206B162E0023D5EE /* SwiftyQueue.swift */,
);
path = Protocols;
sourceTree = "<group>";
};
8B64D1A01DC2E3A100D41A2C /* Meta */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -576,6 +571,7 @@
buildActionMask = 2147483647;
files = (
195A59141E4834F0002B076A /* CBCharacterisic+String.swift in Sources */,
33C3319B247376D400D90A7A /* ConnectionState.swift in Sources */,
33C3318E24735BAB00D90A7A /* Service.swift in Sources */,
19A0686B206B162E0023D5EE /* SwiftyQueue.swift in Sources */,
195A59151E4834F5002B076A /* CBService+String.swift in Sources */,
Expand All @@ -589,7 +585,7 @@
8B64D1DD1DC2F5D000D41A2C /* Device.swift in Sources */,
19A0686D206B18B20023D5EE /* QueueItem.swift in Sources */,
33C3319424735BAB00D90A7A /* Characteristic.swift in Sources */,
19A06869206B130F0023D5EE /* OperationQueue.swift in Sources */,
19A06869206B130F0023D5EE /* OperationQueue+SwiftyQueue.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down

0 comments on commit 8f1a489

Please sign in to comment.