/// <summary>
        /// Scan for nearby BLE device advertisements. Stop scanning when <paramref name="ct" /> is cancelled.
        /// </summary>
        /// <param name="adapter">The adapter to use for scanning</param>
        /// <param name="scanSettings">
        /// Scan settings to configure scan mode and filter out certain advertisements, see:
        /// <see cref="ScanFilter" />
        /// </param>
        /// <param name="advertisementDiscovered">Callback to notify for each discovered advertisement</param>
        /// <param name="timeout">
        /// cancel scan after this length of time. If <c>null</c>, stop scanning after
        /// <see cref="BluetoothLowEnergyUtils.DefaultScanTimeout" />
        /// </param>
        public static Task ScanForBroadcasts([NotNull] this IBluetoothLowEnergyAdapter adapter,
                                             ScanSettings scanSettings, Action <IBlePeripheral> advertisementDiscovered,
                                             TimeSpan?timeout = null)
        {
            if (adapter == null)
            {
                throw new ArgumentNullException(nameof(adapter));
            }

            return(adapter.ScanForBroadcasts(scanSettings, Observer.Create(advertisementDiscovered), timeout));
        }
        /// <summary>
        /// Scan for nearby BLE device advertisements. Stop scanning when <paramref name="ct" /> is cancelled.
        /// </summary>
        /// <param name="adapter">The adapter to use for scanning</param>
        /// <param name="scanSettings">
        /// Scan settings to configure scan mode and filter out certain advertisements, see:
        /// <see cref="ScanFilter" />
        /// </param>
        /// <param name="advertisementDiscovered">Callback to notify for each discovered advertisement</param>
        /// <param name="timeout">
        /// cancel scan after this length of time. If <c>null</c>, stop scanning after
        /// <see cref="BluetoothLowEnergyUtils.DefaultScanTimeout" />
        /// </param>
        public static Task ScanForBroadcasts([NotNull] this IBluetoothLowEnergyAdapter adapter,
                                             ScanSettings scanSettings,
                                             IObserver <IBlePeripheral> advertisementDiscovered,
                                             TimeSpan?timeout = null)
        {
            if (adapter == null)
            {
                throw new ArgumentNullException(nameof(adapter));
            }

            return(adapter.ScanForBroadcasts(
                       scanSettings,
                       advertisementDiscovered,
                       new CancellationTokenSource(timeout ?? BluetoothLowEnergyUtils.DefaultScanTimeout).Token));
        }
        /// <summary>
        /// Attempt to connect to the first device that passes the filter of <paramref name="settings" />, and continue the attempt
        /// until
        /// cancellation token is triggered.
        /// </summary>
        public static async Task <BlePeripheralConnectionRequest> FindAndConnectToDevice(
            [NotNull] this IBluetoothLowEnergyAdapter adapter, ScanSettings settings, CancellationToken ct,
            IProgress <ConnectionProgress> progress = null)
        {
            if (settings.Filter == null)
            {
                throw new ArgumentNullException(
                          nameof(settings),
                          $"Scan settings must have a non-null ScanFilter when calling {nameof(FindAndConnectToDevice)}");
            }

            var cts = CancellationTokenSource.CreateLinkedTokenSource(ct);

            progress?.Report(ConnectionProgress.SearchingForDevice);
            var device = adapter.DiscoveredPeripherals.FirstOrDefault(p => settings.Filter.Passes(p.Advertisement));

            Log.Debug("{0}, device already found? {1}", nameof(FindAndConnectToDevice), device != null);
            if (device == null)
            {
                await adapter.ScanForBroadcasts(
                    settings,
                    Observer.Create(
                        (Action <IBlePeripheral>)(p =>
                {
                    device = p;
                    cts.Cancel();
                })),
                    cts.Token).ConfigureAwait(false);
            }

            return(device == null
            ? ct.IsCancellationRequested
               ?
                   new BlePeripheralConnectionRequest(ConnectionResult.ConnectionAttemptCancelled, null)
               : new BlePeripheralConnectionRequest(ConnectionResult.DeviceNotFound, null)
            : await adapter.ConnectToDevice(device, ct, progress).ConfigureAwait(false));
        }
 /// <summary>
 /// Attempt to connect to the first device that passes <paramref name="filter" />, and continue the attempt until
 /// <paramref name="timeout" /> has elapsed.
 /// </summary>
 public static Task <BlePeripheralConnectionRequest> FindAndConnectToDevice(
     [NotNull] this IBluetoothLowEnergyAdapter adapter, ScanSettings settings, TimeSpan timeout,
     IProgress <ConnectionProgress> progress = null)
 {
     return(FindAndConnectToDevice(adapter, settings, new CancellationTokenSource(timeout).Token, progress));
 }