@@ -0,0 +1,115 @@
import UIKit
import CoreBluetooth
import RxSwift
import RxBluetoothKit
extension CBUUID {
var type : UUID {
return UUID ( rawValue: uuidString) !
}
enum UUID : String {
case main = " 3749FA00-4CED-524B-33D5-F00FD858C4F2 "
case info = " 3749FA01-4CED-524B-33D5-F00FD858C4F2 "
case alert = " 3749FA05-4CED-524B-33D5-F00FD858C4F2 "
var cbuuid : CBUUID { return CBUUID ( string: self . rawValue) }
}
static func common( _ type: UUID ) -> CBUUID {
return type. cbuuid
}
}
extension ObservableType {
func unwrap( ) -> Observable < E > {
return flatMap { $0 == nil ? Observable . empty ( ) : Observable . just ( $0!) }
}
}
extension ObservableType {
public func retryWithDelay( _ timeInterval: RxTimeInterval , maxAttempts: Int ? = nil )
-> Observable < E > {
return retryWhen { ( errors: Observable < Error > ) in
return errors. flatMapWithIndex { ( error, attempt) -> Observable < Int64 > in
if let maxAttempts = maxAttempts, attempt >= maxAttempts - 1 {
return Observable . error ( error)
}
return Observable< Int64> . timer( timeInterval, scheduler: MainScheduler . instance)
}
}
}
}
class Device {
let measure = PublishSubject < Data > ( )
let alert = PublishSubject < Data > ( )
private let disposeBag = DisposeBag ( )
init ( name: String ) {
let manager = BluetoothManager ( queue: . main)
let queue = DispatchQueue ( label: " fr.xdev.rxbluetoothkit.bluetooth " )
let scheduler = SerialDispatchQueueScheduler ( queue: queue, internalSerialQueueName: " " )
let characteristics = manager. rx_state
. filter { $0 == . poweredOn }
. take ( 1 )
. flatMap { _ in manager. scanForPeripherals ( withServices: [ . common( . main) ] ) } // scan
. filter { $0. peripheral. name == name }
. take ( 1 )
. flatMap { $0. peripheral. connect ( ) }
. flatMap { $0. discoverServices ( [ . common( . main) ] ) } // extension on CBUUID to matching enum
. flatMap { Observable . from ( $0) }
. flatMap { $0. discoverCharacteristics ( [ . common( . measure) , . common( . protection) ] ) } // extension on CBUUID to matching enum
. flatMap { Observable . from ( $0) }
characteristics
. filter { $0. uuid. type == . measure } // extension on CBUUID to matching enum
. flatMap { $0. setNotificationAndMonitorUpdates ( ) }
. map { $0. value }
. unwrap ( ) // ignore nil value
. retryWithDelay ( 5 ) // !!!: retry and resubscribe to the full chain on error
. subscribe ( onNext: { [ unowned self] data in
self . measure. onNext ( data!)
} )
. disposed ( by: disposeBag)
characteristics
. filter { $0. uuid. type == . alert } // extension on CBUUID to matching enum
. flatMap { $0. setNotificationAndMonitorUpdates ( ) }
. map { $0. value }
. unwrap ( ) // ignore nil value
. retryWithDelay ( 5 ) // !!!: retry and resubscribe to the full chain on error
. subscribe ( onNext: { [ unowned self] data in
self . alert. onNext ( data!)
} )
. disposed ( by: disposeBag)
}
}
class ViewController : UIViewController {
let disposeBag = DisposeBag ( )
let device = Device ( name: " Device-XXX " )
override func viewDidLoad( ) {
super. viewDidLoad ( )
device. measure
. subscribeOn ( MainScheduler . instance)
. subscribe ( onNext: { data in
print ( " measure: " , [ UInt8] ( data) )
} )
. disposed ( by: disposeBag)
device. alert
. subscribeOn ( MainScheduler . instance)
. subscribe ( onNext: { data in
print ( " alert: " , [ UInt8] ( data) )
} )
. disposed ( by: disposeBag)
}
}