public override IObservable <IScanResult> Scan(ScanConfig config) { if (this.IsScanning) { throw new ArgumentException("There is already an active scan"); } return(Observable.Create <IScanResult>(ob => { this.IsScanning = true; this.context.Clear(); var sub = this .WhenRadioReady() .Where(rdo => rdo != null) .Select(_ => this.CreateScanner(config)) .Switch() .Subscribe( async args => // CAREFUL { var device = this.context.GetPeripheral(args.BluetoothAddress); if (device == null) { var btDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress); if (btDevice != null) { device = this.context.AddOrGetPeripheral(btDevice); } } if (device != null) { var adData = new AdvertisementData(args); var scanResult = new ScanResult(device, args.RawSignalStrengthInDBm, adData); ob.OnNext(scanResult); } }, ob.OnError ); var stopSub = this.scanSubject.Subscribe(_ => { this.IsScanning = false; sub?.Dispose(); ob.OnCompleted(); }); return () => { this.IsScanning = false; sub?.Dispose(); stopSub?.Dispose(); }; })); }
public override IObservable <IScanResult> Scan(ScanConfig config) { if (this.IsScanning) { throw new ArgumentException("There is already an active scan"); } this.isScanning = true; return(this.context .Scan(config ?? new ScanConfig()) .Finally(() => this.isScanning = false)); }
public override IObservable <IScanResult> Scan(ScanConfig config) { config = config ?? new ScanConfig(); if (this.IsScanning) { throw new ArgumentException("There is already an existing scan"); } //if (config.ScanType == BleScanType.Background && (config.ServiceUuids == null || config.ServiceUuids.Count == 0)) // throw new ArgumentException("Background scan type set but not ServiceUUID"); this.context.Clear(); return(this.context .Manager .WhenReady() .Select(_ => Observable.Create <IScanResult>(ob => { var scan = this.context .ScanResultReceived .AsObservable() .Subscribe(ob.OnNext); if (config.ServiceUuids == null || config.ServiceUuids.Count == 0) { this.context.Manager.ScanForPeripherals(null, new PeripheralScanningOptions { AllowDuplicatesKey = true }); } else { var uuids = config.ServiceUuids.Select(o => o.ToCBUuid()).ToArray(); this.context.Manager.ScanForPeripherals(uuids, new PeripheralScanningOptions { AllowDuplicatesKey = true }); } return () => { this.context.Manager.StopScan(); scan.Dispose(); }; })) .Switch()); }
IObservable <BluetoothLEAdvertisementReceivedEventArgs> CreateScanner(ScanConfig config) => Observable.Create <BluetoothLEAdvertisementReceivedEventArgs>(ob => { this.context.Clear(); config = config ?? new ScanConfig { ScanType = BleScanType.Balanced }; var adWatcher = new BluetoothLEAdvertisementWatcher(); if (config.ServiceUuids != null) { foreach (var serviceUuid in config.ServiceUuids) { adWatcher.AdvertisementFilter.Advertisement.ServiceUuids.Add(serviceUuid); } } switch (config.ScanType) { case BleScanType.Balanced: adWatcher.ScanningMode = BluetoothLEScanningMode.Active; break; //case BleScanType.Background: case BleScanType.LowLatency: case BleScanType.LowPowered: adWatcher.ScanningMode = BluetoothLEScanningMode.Passive; break; } var handler = new TypedEventHandler <BluetoothLEAdvertisementWatcher, BluetoothLEAdvertisementReceivedEventArgs> ((sender, args) => ob.OnNext(args) ); adWatcher.Received += handler; adWatcher.Start(); return(() => { adWatcher.Stop(); adWatcher.Received -= handler; }); });
/// <summary> /// Runs BLE scan for a set timespan then pauses for configured timespan before starting again /// </summary> /// <param name="centralManager"></param> /// <param name="scanTime"></param> /// <param name="scanPauseTime"></param> /// <param name="config"></param> /// <returns></returns> public static IObservable <IScanResult> ScanInterval(this ICentralManager centralManager, TimeSpan scanTime, TimeSpan scanPauseTime, ScanConfig config = null) => Observable.Create <IScanResult>(ob =>
/// <summary> /// This method wraps the traditional scan, but waits for the centralManager to be ready before initiating scan /// </summary> /// <param name="centralManager">The centralManager to scan with</param> /// <param name="restart">Stops any current scan running</param> /// <param name="config">ScanConfig parameters you would like to use</param> /// <returns></returns> public static IObservable <IScanResult> Scan(this ICentralManager centralManager, ScanConfig config = null, bool restart = false) { if (restart && centralManager.IsScanning) { centralManager.StopScan(); // need a pause to wait for scan to end } return(centralManager.Scan(config)); }
/// <summary> /// Scans only for distinct peripherals instead of repeating each peripheral scan response - this will only give you peripherals, not RSSI or ad packets /// </summary> /// <param name="centralManager"></param> /// <param name="config"></param> /// <returns></returns> public static IObservable <IPeripheral> ScanForUniquePeripherals(this ICentralManager centralManager, ScanConfig config = null) => centralManager .Scan(config) .Distinct(x => x.Peripheral.Uuid) .Select(x => x.Peripheral);
public abstract IObservable <IScanResult> Scan(ScanConfig config = null);