Last active
January 7, 2019 13:25
-
-
Save monday8am/adc0880095dd81a6f66af91ee24bf5f6 to your computer and use it in GitHub Desktop.
Rx implementation for CBCentralManager API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Lightweight Rx wrapper to CBCentralManager | |
to hide all implementation details. | |
*/ | |
public class RxCBCentralManager { | |
// system API manager | |
private let centralManager: CBCentralManager | |
// internal delegate | |
private let internalDelegate = InternalDelegate() | |
private var lastConnectedDevice: CBPeripheral? | |
public init(queue: DispatchQueue, options: [String: AnyObject]? = nil) { | |
centralManager = CBCentralManager(delegate: internalDelegate, queue: queue, options: options) | |
} | |
public func scanForPeripherals(withServices serviceUUIDs: [CBUUID]?, options: [String: Any]?) -> Observable<CBPeripheral> { | |
centralManager.scanForPeripherals(withServices: serviceUUIDs, options: options) | |
return internalDelegate.didDiscoverPeripheralSubject | |
} | |
public func stopScan() { | |
return centralManager.stopScan() | |
} | |
public func connect(_ peripheral: CBPeripheral, options: [String: Any]?) -> Observable<CBPeripheral> { | |
centralManager.connect(peripheral, options: options) | |
lastConnectedDevice = peripheral // reference needs to be saved! | |
return internalDelegate.didConnectPerihperalSubject | |
} | |
public func cancelPeripheralConnection(_ peripheral: CBPeripheral) -> Observable<CBPeripheral> { | |
centralManager.cancelPeripheralConnection(peripheral) | |
return internalDelegate.didDisconnectPeripheral | |
} | |
public func retrieveConnectedPeripherals(withServices serviceUUIDs: [CBUUID]) -> Observable<[CBPeripheral]> { | |
return Observable.from(optional: centralManager.retrieveConnectedPeripherals(withServices: serviceUUIDs)) | |
} | |
public func retrievePeripherals(withIdentifiers identifiers: [UUID]) -> Observable<[CBPeripheral]> { | |
return Observable.from(optional: centralManager.retrievePeripherals(withIdentifiers: identifiers)) | |
} | |
// Internal delegate to catch callbacks from Bluetooth API | |
// and dispatch the result through subjects | |
private class InternalDelegate: NSObject, CBCentralManagerDelegate { | |
let didDiscoverPeripheralSubject = PublishSubject<CBPeripheral>() | |
let didConnectPerihperalSubject = PublishSubject<CBPeripheral>() | |
let didFailToConnectPeripheralSubject = PublishSubject<CBPeripheral>() | |
let didDisconnectPeripheral = PublishSubject<CBPeripheral>() | |
func centralManager(_: CBCentralManager, | |
didDiscover peripheral: CBPeripheral, | |
advertisementData: [String: Any], | |
rssi: NSNumber) { | |
didDiscoverPeripheralSubject.onNext(peripheral) | |
} | |
func centralManager(_: CBCentralManager, didConnect peripheral: CBPeripheral) { | |
didConnectPerihperalSubject.onNext(peripheral) | |
} | |
func centralManager(_: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { | |
// transform the answers received into singals and dispatch them | |
// using the already created Rx channels | |
if let error = error { | |
didFailToConnectPeripheralSubject.onError(error) | |
} else { | |
didFailToConnectPeripheralSubject.onNext(peripheral) | |
} | |
} | |
func centralManager(_: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { | |
if let error = error { | |
didDisconnectPeripheral.onError(error) | |
} else { | |
didDisconnectPeripheral.onNext(peripheral) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment