using System; using System.Diagnostics; using System.Threading.Tasks; using System.Timers; using Windows.Devices.Bluetooth; using Windows.Devices.Radios; namespace MeetingClock { public class BluetoothManager { public enum BluetoothState { NotInitialized, Exception, NoBluetoothAdapter, NoBluetoothRadio, Disabled, Off, On, Unknown } public delegate void BluetoothStateChangeHandler(BluetoothManager manager, BluetoothState oldState, BluetoothState newState); public event BluetoothStateChangeHandler StateChanged; public BluetoothState State { get; private set; } = BluetoothState.NotInitialized; private BluetoothAdapter adapter; private Radio radio; private Timer updateTimer; public BluetoothManager() { this.updateTimer = new Timer(100); this.updateTimer.Elapsed += UpdateTimer_Elapsed; } public async Task Initialize() { await this.InitializePrivate(true); } private async Task InitializePrivate(bool withLog) { try { this.adapter = await BluetoothAdapter.GetDefaultAsync(); if (this.adapter == null) { if (withLog) { Debug.WriteLine("No BluetoothAdapter found"); } this.State = BluetoothState.NoBluetoothAdapter; this.StateChanged(this, BluetoothState.NotInitialized, BluetoothState.NoBluetoothAdapter); this.updateTimer.Start(); return; } if (withLog) { Debug.WriteLine(String.Format("Found BluetoothAdapter device id: {0}, address: {1}", this.adapter.DeviceId, this.adapter.BluetoothAddress)); } this.radio = await this.adapter.GetRadioAsync(); if (this.radio == null) { if (withLog) { Debug.WriteLine("No Radio found"); } this.State = BluetoothState.NoBluetoothRadio; this.StateChanged(this, BluetoothState.NotInitialized, BluetoothState.NoBluetoothRadio); this.updateTimer.Start(); return; } if (withLog) { Debug.WriteLine(String.Format("Found Bluetooth Radio device: {0}", this.radio.Name)); } this.radio.StateChanged += Radio_StateChanged; this.UpdateState(); if (withLog) { Debug.WriteLine(String.Format("Bluetooth State: {0}", this.State)); } this.updateTimer.Start(); } catch (Exception exception) { if (withLog) { Debug.WriteLine(String.Format("Exception while discovering bluetooth adapter, radio, and state: {0}", exception.Message)); } this.State = BluetoothState.Exception; this.StateChanged(this, BluetoothState.NotInitialized, BluetoothState.Exception); } } private void UpdateState() { RadioState state = this.radio.State; BluetoothState oldState = this.State; BluetoothState btState; switch (state) { case RadioState.Disabled: btState = BluetoothState.Disabled; break; case RadioState.Off: btState = BluetoothState.Off; break; case RadioState.On: btState = BluetoothState.On; break; default: btState = BluetoothState.Unknown; break; } if (btState != this.State) { Debug.WriteLine(String.Format("New Bluetooth state detected. Old state {0}, new state {1}", this.State, btState)); this.State = btState; if (this.StateChanged != null) { this.StateChanged(this, oldState, btState); } } } private void Radio_StateChanged(Radio sender, object args) { this.UpdateState(); } private async void UpdateTimer_Elapsed(object sender, ElapsedEventArgs e) { switch (this.State) { case BluetoothState.Exception: this.updateTimer.Stop(); break; case BluetoothState.NotInitialized: case BluetoothState.NoBluetoothAdapter: case BluetoothState.NoBluetoothRadio: await this.InitializePrivate(false); break; default: this.UpdateState(); break; } } public async Task Enable() { if (this.radio != null) { return await this.radio.SetStateAsync(RadioState.On); } return RadioAccessStatus.Unspecified; } public void Stop() { this.updateTimer.Stop(); } } }