-
Notifications
You must be signed in to change notification settings - Fork 375
3. Scanning peripherals
To start any interaction, with bluetooth devices, you have to first scan some of them. So - get ready!
manager.scanForPeripherals(withServices: serviceIds)
.subscribe(onNext: { scannedPeripheral in
let advertisementData = scannedPeripheral.advertisementData
})
This is the simplest version of this operation. After subscription to observable, scan is performed infinitely. What you receive from method is ScannedPeripheral
instance, that provides access to following information:
- Peripheral: object that you can use, to perform actions like connecting, discovering services etc.
- AdvertisementData: strongly typed wrapper around CBPeripheral advertisement data dictionary.. Thanks to it, you no longer have to worry about all of the keys needed to pull out information.
- RSSI
By default scanning operation is not cancelled. It's the user's responsibility to do that in situations where scanning in not needed anymore. The easiest solutions is just to dispose scanning Disposable
:
let disposable = centralManager.scanForPeripherals(withServices: nil)
.subscribe(onNext: { print("Peripheral scaned \($0)") })
// after some time
disposable.dispose()
Here are other possibilities, thanks to awesome RxSwift operators:
manager.scanForPeripherals(withServices: [serviceIds]).take(1)
//Doing this, after first received result, scan is immediately cancelled.
Ok, that's fun, but what if you also want to apply timeout policy? That's also easy to do:
manager.scanForPeripherals(withServices: [serviceIds]).timeout(3.0, timerScheduler)
As you can see: thanks to all available RxSwift operators, in a simple way you might create really interesting and complex usage scenarios, like for example retrying scans, if you receive timeout.
As describe in Manager State, in order to perform work with bluetooth, your manager should be in .poweredOn state.
Let's see how it looks with scanning:
manager.observeState()
.startWith(manager.state)
.filter { $0 == .poweredOn }
.timeout(3.0, scheduler)
.take(1)
.flatMap { _ in manager.scanForPeripherals(withServices: [serviceId]) }
Firstly, use CentralManager.state
as a start value, next filter .poweredOn from states stream. Like above, we want to apply timeout policy to state changes. Also, we use take to be sure, that after getting .poweredOn state, nothing else ever will be emitted by the observable.
In last flatMap
operation bluetooth is ready to perform further operations.