Zzz – Rev 1

Subversion Repositories:
Rev:
using System;
using System.Threading;
using System.Threading.Tasks;
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Sockets;
using Serilog;
using Zzz.Properties;

namespace Zzz.Idle
{
    public class BluetoothScan : IDisposable
    {
        #region Public Events & Delegates

        public event EventHandler<EventArgs> BluetoothDeviceDetected;

        #endregion

        #region Private Delegates, Events, Enums, Properties, Indexers and Fields

        private readonly CancellationToken _cancellationToken;

        private readonly Task _scanTask;
        private Configuration.Configuration _configuration;
        private BluetoothClient _bluetoothClient;

        private BluetoothComponent _bluetoothComponent;

        private CancellationTokenSource _cancellationTokenSource;

        #endregion

        #region Constructors, Destructors and Finalizers

        public BluetoothScan(Configuration.Configuration configuration) : this()
        {
            _configuration = configuration;
        }

        private BluetoothScan()
        {
            _bluetoothClient = new BluetoothClient();
            _bluetoothComponent = new BluetoothComponent(_bluetoothClient);

            _bluetoothComponent.DiscoverDevicesComplete += BluetoothComponent_DiscoverDevicesComplete;
            _bluetoothComponent.DiscoverDevicesProgress += BluetoothComponent_DiscoverDevicesProgress;

            _cancellationTokenSource = new CancellationTokenSource();
            _cancellationToken = _cancellationTokenSource.Token;

            _scanTask = Scan(_cancellationToken);
        }

        public void Dispose()
        {
            _cancellationTokenSource?.Cancel();

            _scanTask.Wait(CancellationToken.None);

            _cancellationTokenSource = null;

            if (_bluetoothComponent != null)
            {
                _bluetoothComponent.DiscoverDevicesComplete -= BluetoothComponent_DiscoverDevicesComplete;
                _bluetoothComponent.DiscoverDevicesProgress -= BluetoothComponent_DiscoverDevicesProgress;

                _bluetoothComponent?.Dispose();
                _bluetoothComponent = null;
            }

            _bluetoothClient?.Close();
            _bluetoothClient?.Dispose();
            _bluetoothClient = null;
        }

        #endregion

        #region Event Handlers

        private void BluetoothComponent_DiscoverDevicesProgress(object sender, DiscoverDevicesEventArgs e)
        {
            foreach (var deviceInfo in e.Devices)
            {
                Log.Information($"Found bluetooth device {deviceInfo.DeviceName}");

                if (_configuration.BluetoothWatchList.Contains(deviceInfo.DeviceName))
                {
                    Log.Information($"Matching bluetooth device {deviceInfo.DeviceName} detected.");

                    BluetoothDeviceDetected?.Invoke(this, EventArgs.Empty);
                }
            }
        }

        private void BluetoothComponent_DiscoverDevicesComplete(object sender, DiscoverDevicesEventArgs e)
        {
            Log.Information("Bluetooth scan completed.");
        }

        #endregion

        #region Private Methods

        private async Task Scan(CancellationToken cancellationToken)
        {
            try
            {
                do
                {
                    try
                    {
                        await Task.Delay(TimeSpan.FromMinutes((int)_configuration.BluetoothScanInterval),
                            cancellationToken);

                        if (!BluetoothRadio.IsSupported)
                        {
                            Log.Information("Bluetooth radio is not supported.");
                            return;
                        }

                        _bluetoothComponent.DiscoverDevicesAsync(255, true, true, true, true, null);

                        Log.Information("Bluetooth scan started.");
                    }
                    catch (TaskCanceledException)
                    {
                        // ignore task cancellations
                    }
                    catch (Exception ex)
                    {
                        Log.Warning(ex, "Bluetooth scan failure.");
                    }
                } while (!cancellationToken.IsCancellationRequested);
            }
            catch (Exception ex)
            {
                Log.Warning(ex, "Bluetooth thread terminated.");
            }
        }

        #endregion
    }
}

Generated by GNU Enscript 1.6.5.90.