Skip to content

Instantly share code, notes, and snippets.

@monday8am
Last active January 7, 2019 13:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save monday8am/adc0880095dd81a6f66af91ee24bf5f6 to your computer and use it in GitHub Desktop.
Save monday8am/adc0880095dd81a6f66af91ee24bf5f6 to your computer and use it in GitHub Desktop.
Rx implementation for CBCentralManager API
/**
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