From e9bf3c0b24c43c0c26ed9acec3a2f7fd08d58dee Mon Sep 17 00:00:00 2001 From: PolarGoose Date: Sun, 27 Mar 2022 11:47:01 +0200 Subject: [PATCH] * Only consider paired devices when unpair devices by name * Improve code quality --- .gitignore | 1 + README.md | 2 +- src/Bluetooth/Adapters/Adapter.cs | 44 ++++--- src/Bluetooth/Adapters/AdapterFinder.cs | 40 +++---- src/Bluetooth/Adapters/AdapterMacAddress.cs | 15 ++- src/Bluetooth/Devices/BluetoothDevice.cs | 33 +++--- src/Bluetooth/Devices/BluetoothLeDevice.cs | 41 +++---- src/Bluetooth/Devices/Device.cs | 67 ++++++----- src/Bluetooth/Devices/DeviceDiscoverer.cs | 69 ++++++----- src/Bluetooth/Devices/DeviceInfoId.cs | 33 +++--- src/Bluetooth/Devices/DeviceMacAddress.cs | 9 +- src/Bluetooth/Devices/DevicePairer.cs | 115 +++++++++---------- src/Bluetooth/Devices/DeviceUnPairer.cs | 31 +++-- src/Bluetooth/Devices/Utils/AsqFilter.cs | 59 +++++----- src/Bluetooth/Devices/Utils/DeviceWatcher.cs | 83 ++++++------- src/Bluetooth/MacAddress.cs | 49 ++++---- src/Commands/DiscoverDevices.cs | 71 ++++++------ src/Commands/ListAdapters.cs | 49 ++++---- src/Commands/PairDeviceByMac.cs | 33 +++--- src/Commands/PairDeviceByName.cs | 47 ++++---- src/Commands/UnPairDeviceByMac.cs | 23 ++-- src/Commands/UnPairDeviceByName.cs | 29 ++--- src/Commands/Utils/CommonOptions.cs | 51 ++++---- src/Commands/Utils/DeviceFinder.cs | 38 +++--- src/Directory.Build.props | 3 +- src/Program.cs | 55 ++++----- 26 files changed, 522 insertions(+), 568 deletions(-) diff --git a/.gitignore b/.gitignore index 26b383f..2160bad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /build/ .vs/ /src/FodyWeavers.xsd +/.idea diff --git a/README.md b/README.md index 0d7ae94..ba1aa73 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ The program uses * [Windows.Devices.Enumeration API](https://docs.microsoft.com/en-us/uwp/api/Windows.Devices.Enumeration?redirectedfrom=MSDN&view=winrt-22000) to work with Bluetooth. * [Costura Fody](https://github.com/Fody/Costura) to create a single file executable. -## Device pairing by name +### Device pairing by name In order to pair a device by name, the utility starts with discovering all available devices and tries to find a device with the required name. After a device is found its mac address is used to request pairing. The command will fail if there are several devices with the same name. # Return values diff --git a/src/Bluetooth/Adapters/Adapter.cs b/src/Bluetooth/Adapters/Adapter.cs index 94db5e6..f3039c3 100644 --- a/src/Bluetooth/Adapters/Adapter.cs +++ b/src/Bluetooth/Adapters/Adapter.cs @@ -1,31 +1,29 @@ using System; -namespace BluetoothDevicePairing.Bluetooth.Adapter +namespace BluetoothDevicePairing.Bluetooth.Adapters; + +internal sealed class Adapter { - internal sealed class Adapter - { - private readonly Windows.Devices.Enumeration.DeviceInformation adapterInfo; - private readonly Windows.Devices.Bluetooth.BluetoothAdapter adapterDevice; - private readonly Windows.Devices.Radios.Radio radio; + private readonly Windows.Devices.Enumeration.DeviceInformation adapterInfo; + private readonly Windows.Devices.Radios.Radio radio; - public Windows.Devices.Radios.RadioState State => radio.State; - public string Name => adapterInfo.Name; - public AdapterMacAddress MacAddress { get; } - public bool IsDefault { get; } + public Windows.Devices.Radios.RadioState State => radio.State; + public string Name => adapterInfo.Name; + public AdapterMacAddress MacAddress { get; } + public bool IsDefault { get; } - public Adapter(Windows.Devices.Enumeration.DeviceInformation bluetoothAdapterInfo, - AdapterMacAddress defaultAdapterMacAddress) - { - adapterInfo = bluetoothAdapterInfo; - adapterDevice = Windows.Devices.Bluetooth.BluetoothAdapter.FromIdAsync(bluetoothAdapterInfo.Id).GetAwaiter().GetResult(); - radio = adapterDevice.GetRadioAsync().GetAwaiter().GetResult(); - MacAddress = new AdapterMacAddress(adapterDevice); - IsDefault = MacAddress.RawAddess == defaultAdapterMacAddress.RawAddess; - } + public Adapter(Windows.Devices.Enumeration.DeviceInformation bluetoothAdapterInfo, + AdapterMacAddress defaultAdapterMacAddress) + { + adapterInfo = bluetoothAdapterInfo; + var adapterDevice = Windows.Devices.Bluetooth.BluetoothAdapter.FromIdAsync(bluetoothAdapterInfo.Id).GetAwaiter().GetResult(); + radio = adapterDevice.GetRadioAsync().GetAwaiter().GetResult(); + MacAddress = new AdapterMacAddress(adapterDevice); + IsDefault = MacAddress.RawAddress == defaultAdapterMacAddress.RawAddress; + } - public override string ToString() - { - return $"name:'{Name}' mac:'{MacAddress}' state:'{State}'"; - } + public override string ToString() + { + return $"name:'{Name}' mac:'{MacAddress}' state:'{State}'"; } } diff --git a/src/Bluetooth/Adapters/AdapterFinder.cs b/src/Bluetooth/Adapters/AdapterFinder.cs index c8d6de0..d0c1c13 100644 --- a/src/Bluetooth/Adapters/AdapterFinder.cs +++ b/src/Bluetooth/Adapters/AdapterFinder.cs @@ -2,32 +2,26 @@ using System.Collections.Generic; using System.Linq; -namespace BluetoothDevicePairing.Bluetooth.Adapter +namespace BluetoothDevicePairing.Bluetooth.Adapters; + +internal static class AdapterFinder { - internal static class AdapterFinder + public static IEnumerable FindBluetoothAdapters() { - public static Adapter FindDefaultAdapter() - { - return FindBluetoothAdapters().Where(adapter => adapter.IsDefault).Single(); - } - - public static IEnumerable FindBluetoothAdapters() - { - var macOfDefaultAdapter = GetMacAddressOfDefaultAdapter(); - return Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(Windows.Devices.Bluetooth.BluetoothAdapter.GetDeviceSelector()).GetAwaiter().GetResult() - .Select(info => new Adapter(info, macOfDefaultAdapter)) - .ToList(); - } + var macOfDefaultAdapter = GetMacAddressOfDefaultAdapter(); + return Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(Windows.Devices.Bluetooth.BluetoothAdapter.GetDeviceSelector()).GetAwaiter().GetResult() + .Select(info => new Adapter(info, macOfDefaultAdapter)) + .ToList(); + } - private static AdapterMacAddress GetMacAddressOfDefaultAdapter() - { - var defaultAdapter = GetDefaultAdapter(); - return new(defaultAdapter); - } + private static AdapterMacAddress GetMacAddressOfDefaultAdapter() + { + var defaultAdapter = GetDefaultAdapter(); + return new(defaultAdapter); + } - private static Windows.Devices.Bluetooth.BluetoothAdapter GetDefaultAdapter() - { - return Windows.Devices.Bluetooth.BluetoothAdapter.GetDefaultAsync().GetAwaiter().GetResult(); - } + private static Windows.Devices.Bluetooth.BluetoothAdapter GetDefaultAdapter() + { + return Windows.Devices.Bluetooth.BluetoothAdapter.GetDefaultAsync().GetAwaiter().GetResult(); } } diff --git a/src/Bluetooth/Adapters/AdapterMacAddress.cs b/src/Bluetooth/Adapters/AdapterMacAddress.cs index c04f4eb..be8f992 100644 --- a/src/Bluetooth/Adapters/AdapterMacAddress.cs +++ b/src/Bluetooth/Adapters/AdapterMacAddress.cs @@ -1,13 +1,12 @@ -namespace BluetoothDevicePairing.Bluetooth.Adapter +namespace BluetoothDevicePairing.Bluetooth.Adapters; + +internal sealed class AdapterMacAddress : MacAddress { - internal sealed class AdapterMacAddress : MacAddress + public AdapterMacAddress(Windows.Devices.Bluetooth.BluetoothAdapter adapter) : base(adapter.BluetoothAddress) { - public AdapterMacAddress(Windows.Devices.Bluetooth.BluetoothAdapter adapter) : base(adapter.BluetoothAddress) - { - } + } - public AdapterMacAddress(string mac) : base(mac) - { - } + public AdapterMacAddress(string mac) : base(mac) + { } } diff --git a/src/Bluetooth/Devices/BluetoothDevice.cs b/src/Bluetooth/Devices/BluetoothDevice.cs index 00a054f..5150ae8 100644 --- a/src/Bluetooth/Devices/BluetoothDevice.cs +++ b/src/Bluetooth/Devices/BluetoothDevice.cs @@ -1,25 +1,24 @@ using System; -namespace BluetoothDevicePairing.Bluetooth.Devices +namespace BluetoothDevicePairing.Bluetooth.Devices; + +internal sealed class BluetoothDevice : Device { - internal sealed class BluetoothDevice : Device - { - public readonly Windows.Devices.Bluetooth.BluetoothDevice device; - protected override bool IsConnected => device.ConnectionStatus == Windows.Devices.Bluetooth.BluetoothConnectionStatus.Connected; + private readonly Windows.Devices.Bluetooth.BluetoothDevice device; + protected override bool IsConnected => device.ConnectionStatus == Windows.Devices.Bluetooth.BluetoothConnectionStatus.Connected; - private BluetoothDevice(Windows.Devices.Bluetooth.BluetoothDevice device) : base(device.DeviceInformation) - { - this.device = device; - } + private BluetoothDevice(Windows.Devices.Bluetooth.BluetoothDevice device) : base(device.DeviceInformation) + { + this.device = device; + } - public static BluetoothDevice FromDeviceInfo(Windows.Devices.Enumeration.DeviceInformation info) - { - return new BluetoothDevice(Windows.Devices.Bluetooth.BluetoothDevice.FromIdAsync(info.Id).GetAwaiter().GetResult()); - } + public static BluetoothDevice FromDeviceInfo(Windows.Devices.Enumeration.DeviceInformation info) + { + return new BluetoothDevice(Windows.Devices.Bluetooth.BluetoothDevice.FromIdAsync(info.Id).GetAwaiter().GetResult()); + } - public static BluetoothDevice FromMac(DeviceMacAddress mac) - { - return new BluetoothDevice(Windows.Devices.Bluetooth.BluetoothDevice.FromBluetoothAddressAsync(mac.RawAddess).GetAwaiter().GetResult()); - } + public static BluetoothDevice FromMac(DeviceMacAddress mac) + { + return new BluetoothDevice(Windows.Devices.Bluetooth.BluetoothDevice.FromBluetoothAddressAsync(mac.RawAddress).GetAwaiter().GetResult()); } } diff --git a/src/Bluetooth/Devices/BluetoothLeDevice.cs b/src/Bluetooth/Devices/BluetoothLeDevice.cs index b3e9bd4..704d7b6 100644 --- a/src/Bluetooth/Devices/BluetoothLeDevice.cs +++ b/src/Bluetooth/Devices/BluetoothLeDevice.cs @@ -1,30 +1,27 @@ using System; -namespace BluetoothDevicePairing.Bluetooth.Devices +namespace BluetoothDevicePairing.Bluetooth.Devices; + +internal class BluetoothLeDevice : Device { - internal class BluetoothLeDevice : Device - { - private readonly Windows.Devices.Bluetooth.BluetoothLEDevice device; - protected override bool IsConnected => device.ConnectionStatus == Windows.Devices.Bluetooth.BluetoothConnectionStatus.Connected; + private readonly Windows.Devices.Bluetooth.BluetoothLEDevice device; + protected override bool IsConnected => device.ConnectionStatus == Windows.Devices.Bluetooth.BluetoothConnectionStatus.Connected; - private BluetoothLeDevice(Windows.Devices.Bluetooth.BluetoothLEDevice device) : base(device.DeviceInformation) - { - this.device = device; - } + private BluetoothLeDevice(Windows.Devices.Bluetooth.BluetoothLEDevice device) : base(device.DeviceInformation) + { + this.device = device; + } - public static BluetoothLeDevice FromDeviceInfo(Windows.Devices.Enumeration.DeviceInformation info) - { - return new BluetoothLeDevice(Windows.Devices.Bluetooth.BluetoothLEDevice.FromIdAsync(info.Id).GetAwaiter().GetResult()); - } + public static BluetoothLeDevice FromDeviceInfo(Windows.Devices.Enumeration.DeviceInformation info) + { + return new BluetoothLeDevice(Windows.Devices.Bluetooth.BluetoothLEDevice.FromIdAsync(info.Id).GetAwaiter().GetResult()); + } - public static BluetoothLeDevice FromMac(DeviceMacAddress mac) - { - var device = Windows.Devices.Bluetooth.BluetoothLEDevice.FromBluetoothAddressAsync(mac.RawAddess).GetAwaiter().GetResult(); - if(device == null) - { - throw new Exception($"Can't create a BluetoothLE device from the provided mac address '{mac}'. Device with this mac address doesn't exist"); - } - return new BluetoothLeDevice(device); - } + public static BluetoothLeDevice FromMac(DeviceMacAddress mac) + { + var device = Windows.Devices.Bluetooth.BluetoothLEDevice.FromBluetoothAddressAsync(mac.RawAddress).GetAwaiter().GetResult(); + return device == null + ? throw new Exception($"Can't create a BluetoothLE device from the provided mac address '{mac}'. Device with this mac address doesn't exist") + : new BluetoothLeDevice(device); } } diff --git a/src/Bluetooth/Devices/Device.cs b/src/Bluetooth/Devices/Device.cs index 18d91a0..c6e6627 100644 --- a/src/Bluetooth/Devices/Device.cs +++ b/src/Bluetooth/Devices/Device.cs @@ -1,42 +1,41 @@ -namespace BluetoothDevicePairing.Bluetooth.Devices +namespace BluetoothDevicePairing.Bluetooth.Devices; + +internal enum ConnectionStatus { - internal enum ConnectionStatus - { - NotPaired, - Paired, - Connected - } + NotPaired, + Paired, + Connected +} - internal enum DeviceType - { - Bluetooth, - BluetoothLE - } +internal enum DeviceType +{ + Bluetooth, + BluetoothLE +} - internal abstract class Device - { - private readonly Windows.Devices.Enumeration.DeviceInformation info; - protected abstract bool IsConnected { get; } +internal abstract class Device +{ + private readonly Windows.Devices.Enumeration.DeviceInformation info; + protected abstract bool IsConnected { get; } - public ConnectionStatus ConnectionStatus => - IsConnected - ? ConnectionStatus.Connected - : PairingInfo.IsPaired - ? ConnectionStatus.Paired - : ConnectionStatus.NotPaired; - public Windows.Devices.Enumeration.DeviceInformationPairing PairingInfo => info.Pairing; - public DeviceInfoId Id { get; } - public string Name => info.Name; + public ConnectionStatus ConnectionStatus => + IsConnected + ? ConnectionStatus.Connected + : PairingInfo.IsPaired + ? ConnectionStatus.Paired + : ConnectionStatus.NotPaired; + public Windows.Devices.Enumeration.DeviceInformationPairing PairingInfo => info.Pairing; + public DeviceInfoId Id { get; } + public string Name => info.Name; - protected Device(Windows.Devices.Enumeration.DeviceInformation info) - { - this.info = info; - Id = new DeviceInfoId(info); - } + protected Device(Windows.Devices.Enumeration.DeviceInformation info) + { + this.info = info; + Id = new DeviceInfoId(info); + } - public override string ToString() - { - return $"name:'{Name}' mac:'{Id.DeviceMac}' type:'{Id.DeviceType}' ConnectionStatus:'{ConnectionStatus}'"; - } + public override string ToString() + { + return $"name:'{Name}' mac:'{Id.DeviceMac}' type:'{Id.DeviceType}' ConnectionStatus:'{ConnectionStatus}'"; } } diff --git a/src/Bluetooth/Devices/DeviceDiscoverer.cs b/src/Bluetooth/Devices/DeviceDiscoverer.cs index 1d0ce1a..4bd9c62 100644 --- a/src/Bluetooth/Devices/DeviceDiscoverer.cs +++ b/src/Bluetooth/Devices/DeviceDiscoverer.cs @@ -4,51 +4,50 @@ using System.Linq; using System.Threading; -namespace BluetoothDevicePairing.Bluetooth.Devices +namespace BluetoothDevicePairing.Bluetooth.Devices; + +internal sealed class DiscoveryTime { - internal class DiscoveryTime - { - public int Seconds { get; } + public int Seconds { get; } - public DiscoveryTime(int timeInSeconds) + public DiscoveryTime(int timeInSeconds) + { + if (timeInSeconds is < 1 or > 30) { - if (timeInSeconds < 1 || timeInSeconds > 30) - { - throw new Exception($"discovery time should be in range [1; 30] but was {timeInSeconds}"); - } - - Seconds = timeInSeconds; + throw new Exception($"discovery time should be in range [1; 30] but was {timeInSeconds}"); } + + Seconds = timeInSeconds; } +} - internal static class DeviceDiscoverer +internal static class DeviceDiscoverer +{ + public static List DiscoverBluetoothDevices(DiscoveryTime time) { - public static List DiscoverBluetoothDevices(DiscoveryTime time) - { - return Discover(AsqFilter.BluetoothDevicesFilter(), time); - } + return Discover(AsqFilter.BluetoothDevicesFilter(), time); + } - public static List DiscoverPairedBluetoothDevices(DiscoveryTime time) - { - return Discover(AsqFilter.PairedBluetoothDevicesFilter(), time); - } + public static List DiscoverPairedBluetoothDevices(DiscoveryTime time) + { + return Discover(AsqFilter.PairedBluetoothDevicesFilter(), time); + } - private static List Discover(AsqFilter filter, DiscoveryTime time) - { - Console.WriteLine($"Start discovering devices for {time.Seconds} seconds"); + private static List Discover(AsqFilter filter, DiscoveryTime time) + { + Console.WriteLine($"Start discovering devices for {time.Seconds} seconds"); - var watcher = new DeviceWatcher(filter); - watcher.Start(); - Thread.Sleep(time.Seconds * 1000); - var devices = watcher.Stop(); - return devices.Select(info => CreateDevice(info)).ToList(); - } + var watcher = new DeviceWatcher(filter); + watcher.Start(); + Thread.Sleep(time.Seconds * 1000); + var devices = watcher.Stop(); + return devices.Select(CreateDevice).ToList(); + } - private static Device CreateDevice(Windows.Devices.Enumeration.DeviceInformation info) - { - return new DeviceInfoId(info).DeviceType == DeviceType.Bluetooth - ? BluetoothDevice.FromDeviceInfo(info) - : BluetoothLeDevice.FromDeviceInfo(info); - } + private static Device CreateDevice(Windows.Devices.Enumeration.DeviceInformation info) + { + return new DeviceInfoId(info).DeviceType == DeviceType.Bluetooth + ? BluetoothDevice.FromDeviceInfo(info) + : BluetoothLeDevice.FromDeviceInfo(info); } } diff --git a/src/Bluetooth/Devices/DeviceInfoId.cs b/src/Bluetooth/Devices/DeviceInfoId.cs index 80086f7..21c1f16 100644 --- a/src/Bluetooth/Devices/DeviceInfoId.cs +++ b/src/Bluetooth/Devices/DeviceInfoId.cs @@ -1,26 +1,25 @@ -using BluetoothDevicePairing.Bluetooth.Adapter; using System; using System.Text.RegularExpressions; +using BluetoothDevicePairing.Bluetooth.Adapters; -namespace BluetoothDevicePairing.Bluetooth.Devices +namespace BluetoothDevicePairing.Bluetooth.Devices; + +internal sealed class DeviceInfoId { - internal sealed class DeviceInfoId - { - public DeviceType DeviceType { get; } - public AdapterMacAddress AdapterMac { get; } - public DeviceMacAddress DeviceMac { get; } + public DeviceType DeviceType { get; } + public DeviceMacAddress DeviceMac { get; } + private AdapterMacAddress AdapterMac { get; } - public DeviceInfoId(Windows.Devices.Enumeration.DeviceInformation info) + public DeviceInfoId(Windows.Devices.Enumeration.DeviceInformation info) + { + var match = Regex.Match(info.Id, @"(^\w+)#(?Bluetooth|BluetoothLE)(?(..:){5}(..))-(?(..:){5}(..))$"); + if (!match.Success) { - var match = Regex.Match(info.Id, @"(^\w+)#(?Bluetooth|BluetoothLE)(?(..:){5}(..))-(?(..:){5}(..))$"); - if (!match.Success) - { - throw new Exception($"Failed to parse DeviceInformation.Id '{info.Id}'"); - } - - DeviceType = match.Groups["Type"].Value == "Bluetooth" ? DeviceType.Bluetooth : DeviceType.BluetoothLE; - AdapterMac = new AdapterMacAddress(match.Groups["AdapterMac"].Value); - DeviceMac = new DeviceMacAddress(match.Groups["DeviceMac"].Value); + throw new Exception($"Failed to parse DeviceInformation.Id '{info.Id}'"); } + + DeviceType = match.Groups["Type"].Value == "Bluetooth" ? DeviceType.Bluetooth : DeviceType.BluetoothLE; + AdapterMac = new AdapterMacAddress(match.Groups["AdapterMac"].Value); + DeviceMac = new DeviceMacAddress(match.Groups["DeviceMac"].Value); } } diff --git a/src/Bluetooth/Devices/DeviceMacAddress.cs b/src/Bluetooth/Devices/DeviceMacAddress.cs index f1ef744..f77f4f7 100644 --- a/src/Bluetooth/Devices/DeviceMacAddress.cs +++ b/src/Bluetooth/Devices/DeviceMacAddress.cs @@ -1,9 +1,8 @@ -namespace BluetoothDevicePairing.Bluetooth.Devices +namespace BluetoothDevicePairing.Bluetooth.Devices; + +internal sealed class DeviceMacAddress : MacAddress { - internal sealed class DeviceMacAddress : MacAddress + public DeviceMacAddress(string mac) : base(mac) { - public DeviceMacAddress(string mac) : base(mac) - { - } } } diff --git a/src/Bluetooth/Devices/DevicePairer.cs b/src/Bluetooth/Devices/DevicePairer.cs index 18f28f6..2742ef1 100644 --- a/src/Bluetooth/Devices/DevicePairer.cs +++ b/src/Bluetooth/Devices/DevicePairer.cs @@ -1,78 +1,77 @@ using System; -namespace BluetoothDevicePairing.Bluetooth.Devices +namespace BluetoothDevicePairing.Bluetooth.Devices; + +internal static class DevicePairer { - internal static class DevicePairer + public static void PairDevice(Device device, string pinCode) { - public static void PairDevice(Device device, string pinCode) - { - Console.WriteLine($"Request to pair device \"{device}\""); - - if (device.ConnectionStatus == ConnectionStatus.Connected) - { - throw new Exception("Device is already connected, no need to pair"); - } - - if (device.ConnectionStatus == ConnectionStatus.Paired) - { - throw new Exception("Device is already paired"); - } + Console.WriteLine($"Request to pair device \"{device}\""); - Console.WriteLine("Start pairing"); - Pair(device.PairingInfo, pinCode); - Console.WriteLine("Device has been successfully paired"); + if (device.ConnectionStatus == ConnectionStatus.Connected) + { + throw new Exception("Device is already connected, no need to pair"); } - private static void Pair(Windows.Devices.Enumeration.DeviceInformationPairing pairingInfo, string pinCode) + if (device.ConnectionStatus == ConnectionStatus.Paired) { - pairingInfo.Custom.PairingRequested += (s, a) => PairingRequestedHandler(s, a, pinCode); + throw new Exception("Device is already paired"); + } - // DeviceInformation.Pairing.PairAsync function doesn't work for non UWP applications. Thus, DeviceInformation.Pairing.Custom.PairAsync is used. - // https://stackoverflow.com/questions/45191412/deviceinformation-pairasync-not-working-in-wpf + Console.WriteLine("Start pairing"); + Pair(device.PairingInfo, pinCode); + Console.WriteLine("Device has been successfully paired"); + } - // DevicePairingKinds.DisplayPin option conflicts with DevicePairingKinds.ProvidePin: I used "Bluetooth Module HC 05" to test pairing with PIN code. - // This device requires pin code "1234" to be paired. When both DevicePairingKinds.DisplayPin and DevicePairingKinds.ProvidePin flags were used in PairAsync function, - // the PairingRequestedHandler was called with PairingKind equal to DevicePairingKinds.DisplayPin instead of DevicePairingKinds.ProvidePin, which made pairing fail. - // Therefore, I decided not to use DevicePairingKinds.DisplayPin flag. + private static void Pair(Windows.Devices.Enumeration.DeviceInformationPairing pairingInfo, string pinCode) + { + pairingInfo.Custom.PairingRequested += (_, a) => PairingRequestedHandler(a, pinCode); + + // DeviceInformation.Pairing.PairAsync function doesn't work for non UWP applications. Thus, DeviceInformation.Pairing.Custom.PairAsync is used. + // https://stackoverflow.com/questions/45191412/deviceinformation-pairasync-not-working-in-wpf + + // DevicePairingKinds.DisplayPin option conflicts with DevicePairingKinds.ProvidePin: I used "Bluetooth Module HC 05" to test pairing with PIN code. + // This device requires pin code "1234" to be paired. When both DevicePairingKinds.DisplayPin and DevicePairingKinds.ProvidePin flags were used in PairAsync function, + // the PairingRequestedHandler was called with PairingKind equal to DevicePairingKinds.DisplayPin instead of DevicePairingKinds.ProvidePin, which made pairing fail. + // Therefore, I decided not to use DevicePairingKinds.DisplayPin flag. - var res = pairingInfo.Custom.PairAsync(Windows.Devices.Enumeration.DevicePairingKinds.ConfirmOnly | - Windows.Devices.Enumeration.DevicePairingKinds.ProvidePin | - Windows.Devices.Enumeration.DevicePairingKinds.ConfirmPinMatch, - Windows.Devices.Enumeration.DevicePairingProtectionLevel.None) - .GetAwaiter().GetResult().Status; - if (res != Windows.Devices.Enumeration.DevicePairingResultStatus.Paired) - { - throw new Exception($"Failed to pair device. Status = {res}"); - } + var res = pairingInfo.Custom.PairAsync(Windows.Devices.Enumeration.DevicePairingKinds.ConfirmOnly | + Windows.Devices.Enumeration.DevicePairingKinds.ProvidePin | + Windows.Devices.Enumeration.DevicePairingKinds.ConfirmPinMatch, + Windows.Devices.Enumeration.DevicePairingProtectionLevel.None) + .GetAwaiter().GetResult().Status; + if (res != Windows.Devices.Enumeration.DevicePairingResultStatus.Paired) + { + throw new Exception($"Failed to pair device. Status = {res}"); } + } - private static void PairingRequestedHandler(Windows.Devices.Enumeration.DeviceInformationCustomPairing sender, - Windows.Devices.Enumeration.DevicePairingRequestedEventArgs args, - string pin) + private static void PairingRequestedHandler(Windows.Devices.Enumeration.DevicePairingRequestedEventArgs args, + string pin) + { + switch (args.PairingKind) { - switch (args.PairingKind) - { - case Windows.Devices.Enumeration.DevicePairingKinds.ConfirmOnly: - Console.WriteLine("Pairing mode: ConfirmOnly"); - args.Accept(); - return; + case Windows.Devices.Enumeration.DevicePairingKinds.ConfirmOnly: + Console.WriteLine("Pairing mode: ConfirmOnly"); + args.Accept(); + return; - case Windows.Devices.Enumeration.DevicePairingKinds.ProvidePin: - Console.WriteLine("Pairing mode: ProvidePin"); - Console.WriteLine($"Pin is requested by the device. Using '{pin}' as a pin code"); - args.Accept(pin); - return; + case Windows.Devices.Enumeration.DevicePairingKinds.ProvidePin: + Console.WriteLine("Pairing mode: ProvidePin"); + Console.WriteLine($"Pin is requested by the device. Using '{pin}' as a pin code"); + args.Accept(pin); + return; - case Windows.Devices.Enumeration.DevicePairingKinds.ConfirmPinMatch: - Console.WriteLine("Pairing mode: ConfirmPinMatch"); - Console.WriteLine($"The device's pin code: '{args.Pin}'"); - Console.WriteLine("Waiting for the target device to accept the pairing (you probably need to follow the instructions on the target device's screen)"); - args.Accept(); - return; - } + case Windows.Devices.Enumeration.DevicePairingKinds.ConfirmPinMatch: + Console.WriteLine("Pairing mode: ConfirmPinMatch"); + Console.WriteLine($"The device's pin code: '{args.Pin}'"); + Console.WriteLine("Waiting for the target device to accept the pairing (you probably need to follow the instructions on the target device's screen)"); + args.Accept(); + return; - Console.WriteLine($"Unexpected pairing type: {args.PairingKind}"); - throw new Exception(); + default: + Console.WriteLine($"Unexpected pairing type: {args.PairingKind}"); + throw new Exception(); } } } diff --git a/src/Bluetooth/Devices/DeviceUnPairer.cs b/src/Bluetooth/Devices/DeviceUnPairer.cs index a035ac1..15be50b 100644 --- a/src/Bluetooth/Devices/DeviceUnPairer.cs +++ b/src/Bluetooth/Devices/DeviceUnPairer.cs @@ -1,25 +1,24 @@ using System; -namespace BluetoothDevicePairing.Bluetooth.Devices +namespace BluetoothDevicePairing.Bluetooth.Devices; + +internal static class DeviceUnPairer { - internal static class DeviceUnPairer + public static void UnpairDevice(Device device) { - public static void UnpairDevice(Device device) - { - Console.WriteLine($"Request to unpair device \"{device}\""); + Console.WriteLine($"Request to unpair device \"{device}\""); - if (device.ConnectionStatus == ConnectionStatus.NotPaired) - { - throw new Exception("Device is not paired"); - } - - var res = device.PairingInfo.UnpairAsync().GetAwaiter().GetResult().Status; - if (res != Windows.Devices.Enumeration.DeviceUnpairingResultStatus.Unpaired) - { - throw new Exception($"Failed to unpair the device. Status = {res}"); - } + if (device.ConnectionStatus == ConnectionStatus.NotPaired) + { + throw new Exception("Device is not paired"); + } - Console.WriteLine("Device has been successfully unpaired"); + var res = device.PairingInfo.UnpairAsync().GetAwaiter().GetResult().Status; + if (res != Windows.Devices.Enumeration.DeviceUnpairingResultStatus.Unpaired) + { + throw new Exception($"Failed to unpair the device. Status = {res}"); } + + Console.WriteLine("Device has been successfully unpaired"); } } diff --git a/src/Bluetooth/Devices/Utils/AsqFilter.cs b/src/Bluetooth/Devices/Utils/AsqFilter.cs index 1e62038..2ece3f3 100644 --- a/src/Bluetooth/Devices/Utils/AsqFilter.cs +++ b/src/Bluetooth/Devices/Utils/AsqFilter.cs @@ -1,38 +1,37 @@ -namespace BluetoothDevicePairing.Bluetooth.Devices.Utils +namespace BluetoothDevicePairing.Bluetooth.Devices.Utils; + +internal sealed class AsqFilter { - internal sealed class AsqFilter - { - public string Query { get; } + public string Query { get; } - private AsqFilter(string query) - { - Query = query; - } + private AsqFilter(string query) + { + Query = query; + } - public override string ToString() - { - return Query; - } + public override string ToString() + { + return Query; + } - public static AsqFilter BluetoothDevicesFilter() - { - var paired = PairedBluetoothDevicesFilter(); - var nonPaired = NonPairedBluetoothDevicesFilter(); - return new AsqFilter($"({paired}) OR ({nonPaired})"); - } + public static AsqFilter BluetoothDevicesFilter() + { + var paired = PairedBluetoothDevicesFilter(); + var nonPaired = NonPairedBluetoothDevicesFilter(); + return new AsqFilter($"({paired}) OR ({nonPaired})"); + } - public static AsqFilter PairedBluetoothDevicesFilter() - { - var bPaired = Windows.Devices.Bluetooth.BluetoothDevice.GetDeviceSelectorFromPairingState(true); - var blePaired = Windows.Devices.Bluetooth.BluetoothLEDevice.GetDeviceSelectorFromPairingState(true); - return new AsqFilter($"({bPaired}) OR ({blePaired})"); - } + public static AsqFilter PairedBluetoothDevicesFilter() + { + var bPaired = Windows.Devices.Bluetooth.BluetoothDevice.GetDeviceSelectorFromPairingState(true); + var blePaired = Windows.Devices.Bluetooth.BluetoothLEDevice.GetDeviceSelectorFromPairingState(true); + return new AsqFilter($"({bPaired}) OR ({blePaired})"); + } - public static AsqFilter NonPairedBluetoothDevicesFilter() - { - var bNonPaired = Windows.Devices.Bluetooth.BluetoothDevice.GetDeviceSelectorFromPairingState(false); - var bleNonPaired = Windows.Devices.Bluetooth.BluetoothLEDevice.GetDeviceSelectorFromPairingState(false); - return new AsqFilter($"({bNonPaired}) OR ({bleNonPaired})"); - } + private static AsqFilter NonPairedBluetoothDevicesFilter() + { + var bNonPaired = Windows.Devices.Bluetooth.BluetoothDevice.GetDeviceSelectorFromPairingState(false); + var bleNonPaired = Windows.Devices.Bluetooth.BluetoothLEDevice.GetDeviceSelectorFromPairingState(false); + return new AsqFilter($"({bNonPaired}) OR ({bleNonPaired})"); } } diff --git a/src/Bluetooth/Devices/Utils/DeviceWatcher.cs b/src/Bluetooth/Devices/Utils/DeviceWatcher.cs index 5455b3e..0a5ec50 100644 --- a/src/Bluetooth/Devices/Utils/DeviceWatcher.cs +++ b/src/Bluetooth/Devices/Utils/DeviceWatcher.cs @@ -3,63 +3,56 @@ using System.Linq; using System.Threading; -namespace BluetoothDevicePairing.Bluetooth.Devices.Utils +namespace BluetoothDevicePairing.Bluetooth.Devices.Utils; + +internal sealed class DeviceWatcher { - internal sealed class DeviceWatcher + private readonly Windows.Devices.Enumeration.DeviceWatcher watcher; + private readonly AutoResetEvent watcherStoppedEvent = new(false); + private List devices; + + public DeviceWatcher(AsqFilter filter) { - private readonly Windows.Devices.Enumeration.DeviceWatcher watcher; - private readonly AutoResetEvent watcherStoppedEvent = new(false); - private List devices; + watcher = Windows.Devices.Enumeration.DeviceInformation.CreateWatcher(filter.Query, + null, + Windows.Devices.Enumeration.DeviceInformationKind.AssociationEndpoint); - public DeviceWatcher(AsqFilter filter) - { - watcher = Windows.Devices.Enumeration.DeviceInformation.CreateWatcher(filter.Query, - null, - Windows.Devices.Enumeration.DeviceInformationKind.AssociationEndpoint); + watcher.Added += (_, info) => devices.Add(info); - watcher.Added += (s, info) => + watcher.Removed += (_, removedDevice) => + { + foreach (var device in devices.Where(device => device.Id == removedDevice.Id)) { - devices.Add(info); - }; + devices.Remove(device); + } + }; - watcher.Removed += (s, removedDevice) => + watcher.Updated += (_, updatedDevice) => + { + foreach (var device in devices.Where(device => device.Id == updatedDevice.Id)) { - foreach (var device in devices.Where(device => device.Id == removedDevice.Id)) - { - devices.Remove(device); - } - }; + device.Update(updatedDevice); + } + }; - watcher.Updated += (s, updatedDevice) => - { - foreach (var device in devices.Where(device => device.Id == updatedDevice.Id)) - { - device.Update(updatedDevice); - } - }; + watcher.Stopped += (_, _) => watcherStoppedEvent.Set(); + } - watcher.Stopped += (s, o) => - { - watcherStoppedEvent.Set(); - }; - } + public void Start() + { + devices = new(); + watcher.Start(); + } - public void Start() + public IEnumerable Stop() + { + watcher.Stop(); + var receivedSignal = watcherStoppedEvent.WaitOne(5 * 1000); + if (!receivedSignal) { - devices = new(); - watcher.Start(); + Console.WriteLine("Warning: the watcher didn't stop after 5 seconds"); } - public List Stop() - { - watcher.Stop(); - var receivedSignal = watcherStoppedEvent.WaitOne(5 * 1000); - if (!receivedSignal) - { - Console.WriteLine("Warning: the watcher didn't stop after 5 seconds"); - } - - return devices; - } + return devices; } } diff --git a/src/Bluetooth/MacAddress.cs b/src/Bluetooth/MacAddress.cs index 0114fca..061d597 100644 --- a/src/Bluetooth/MacAddress.cs +++ b/src/Bluetooth/MacAddress.cs @@ -2,36 +2,35 @@ using System.Linq; using System.Text.RegularExpressions; -namespace BluetoothDevicePairing.Bluetooth +namespace BluetoothDevicePairing.Bluetooth; + +internal class MacAddress { - internal class MacAddress - { - public string Address { get; } - public ulong RawAddess { get; } + private string Address { get; } + public ulong RawAddress { get; } - public MacAddress(string mac) + protected MacAddress(string mac) + { + var match = Regex.Match(mac, @"^(..:){5}(..)$"); + if (!match.Success) { - var match = Regex.Match(mac, @"^(..:){5}(..)$"); - if (!match.Success) - { - throw new Exception($"MacAddress address '{mac}' is not a valid mac address"); - } - Address = mac; - RawAddess = Convert.ToUInt64(Address.Replace(":", ""), 16); + throw new Exception($"MacAddress address '{mac}' is not a valid mac address"); } + Address = mac; + RawAddress = Convert.ToUInt64(Address.Replace(":", ""), 16); + } - public MacAddress(ulong mac) - { - Address = string.Join(":", BitConverter.GetBytes(mac) - .Reverse() - .Skip(2) - .Select(b => b.ToString("x2"))); - RawAddess = mac; - } + protected MacAddress(ulong mac) + { + Address = string.Join(":", BitConverter.GetBytes(mac) + .Reverse() + .Skip(2) + .Select(b => b.ToString("x2"))); + RawAddress = mac; + } - public override string ToString() - { - return Address; - } + public override string ToString() + { + return Address; } } diff --git a/src/Commands/DiscoverDevices.cs b/src/Commands/DiscoverDevices.cs index 5ee8f31..5558c4a 100644 --- a/src/Commands/DiscoverDevices.cs +++ b/src/Commands/DiscoverDevices.cs @@ -3,50 +3,49 @@ using System; using System.Linq; -namespace BluetoothDevicePairing.Commands +namespace BluetoothDevicePairing.Commands; + +[Verb("discover", + HelpText = "Discover devices. Prints a table with the following fields:\n" + + "|Device type|Mac address|Pairing status|Device name|")] +internal sealed class DiscoverDevicesOptions { - [Verb("discover", - HelpText = "Discover devices. Prints a table with the following fields:\n" + - "|Device type|Mac address|Pairing status|Device name|")] - internal sealed class DiscoverDevicesOptions - { - [Option("discovery-time", - Default = 10, - HelpText = "how long to search for devices. Units: seconds")] - public int DiscoveryTime { get; set; } - } + [Option("discovery-time", + Default = 10, + HelpText = "how long to search for devices. Units: seconds")] + public int DiscoveryTime { get; set; } +} - internal static class DiscoverDevices +internal static class DiscoverDevices +{ + public static void Execute(DiscoverDevicesOptions opts) { - public static void Execute(DiscoverDevicesOptions opts) + var devices = DeviceDiscoverer.DiscoverBluetoothDevices(new DiscoveryTime(opts.DiscoveryTime)).OrderBy(d => d.Name); + Console.WriteLine(new string('-', 73)); + foreach (var d in devices) { - var devices = DeviceDiscoverer.DiscoverBluetoothDevices(new DiscoveryTime(opts.DiscoveryTime)).OrderBy(d => d.Name); - Console.WriteLine(new string('-', 73)); - foreach (var d in devices) - { - PrintDevice(d); - } - Console.WriteLine(new string('-', 73)); + PrintDevice(d); } + Console.WriteLine(new string('-', 73)); + } - private static void PrintDevice(Device d) - { - Console.WriteLine($"|{GetType(d),2}|{d.Id.DeviceMac}|{GetConnectionStatus(d),-9}|{GetName(d),-40}|"); - } + private static void PrintDevice(Device d) + { + Console.WriteLine($"|{GetType(d),2}|{d.Id.DeviceMac}|{GetConnectionStatus(d),-9}|{GetName(d),-40}|"); + } - private static string GetType(Device d) - { - return d.Id.DeviceType == DeviceType.BluetoothLE ? "LE" : ""; - } + private static string GetType(Device d) + { + return d.Id.DeviceType == DeviceType.BluetoothLE ? "LE" : ""; + } - private static string GetName(Device d) - { - return d.Name == "" ? "" : d.Name; - } + private static string GetName(Device d) + { + return d.Name == "" ? "" : d.Name; + } - private static string GetConnectionStatus(Device d) - { - return d.ConnectionStatus == ConnectionStatus.NotPaired ? "" : d.ConnectionStatus.ToString(); - } + private static string GetConnectionStatus(Device d) + { + return d.ConnectionStatus == ConnectionStatus.NotPaired ? "" : d.ConnectionStatus.ToString(); } } diff --git a/src/Commands/ListAdapters.cs b/src/Commands/ListAdapters.cs index d2f5f3a..170359b 100644 --- a/src/Commands/ListAdapters.cs +++ b/src/Commands/ListAdapters.cs @@ -1,37 +1,36 @@ -using BluetoothDevicePairing.Bluetooth.Adapter; using CommandLine; using System; +using BluetoothDevicePairing.Bluetooth.Adapters; -namespace BluetoothDevicePairing.Commands +namespace BluetoothDevicePairing.Commands; + +[Verb("list-adapters", + HelpText = "Lists bluetooth adapters. Prints a table with the following fields:\n" + + "|Is default|Radio mac address|Name|State|")] +internal sealed class ListAdaptersOptions { - [Verb("list-adapters", - HelpText = "Lists bluetooth adapters. Prints a table with the following fields:\n" + - "|Is default|Radio mac address|Name|State|")] - internal sealed class ListAdaptersOptions - { - } +} - internal static class ListAdapters +internal static class ListAdapters +{ + public static void Execute(ListAdaptersOptions _) { - public static void Execute(ListAdaptersOptions opts) + var adapters = AdapterFinder.FindBluetoothAdapters(); + Console.WriteLine(new string('-', 71)); + foreach (var a in adapters) { - var adapters = AdapterFinder.FindBluetoothAdapters(); - Console.WriteLine(new string('-', 71)); - foreach (var a in adapters) - { - PrintAdapter(a); - } - Console.WriteLine(new string('-', 71)); + PrintAdapter(a); } + Console.WriteLine(new string('-', 71)); + } - private static void PrintAdapter(Adapter a) - { - Console.WriteLine($"|{GetIsDefailt(a),1}|{a.MacAddress}|{a.Name,-40}|{a.State,-8}|"); - } + private static void PrintAdapter(Adapter a) + { + Console.WriteLine($"|{IsDefault(a),1}|{a.MacAddress}|{a.Name,-40}|{a.State,-8}|"); + } - private static string GetIsDefailt(Adapter a) - { - return a.IsDefault ? "*" : ""; - } + private static string IsDefault(Adapter a) + { + return a.IsDefault ? "*" : ""; } } diff --git a/src/Commands/PairDeviceByMac.cs b/src/Commands/PairDeviceByMac.cs index 89ec1ad..f18d153 100644 --- a/src/Commands/PairDeviceByMac.cs +++ b/src/Commands/PairDeviceByMac.cs @@ -2,25 +2,24 @@ using BluetoothDevicePairing.Commands.Utils; using CommandLine; -namespace BluetoothDevicePairing.Commands +namespace BluetoothDevicePairing.Commands; + +[Verb("pair-by-mac", + HelpText = "Pair a device using its mac address")] +internal sealed class PairDeviceByMacOptions : MacAndDeviceTypeOptions { - [Verb("pair-by-mac", - HelpText = "Pair a device using its mac address")] - internal sealed class PairDeviceByMacOptions : MacAndDeviceTypeOptions - { - [Option("pin", - Default = "0000", - HelpText = "pin code to provide to a device if it requires it for pairing")] - public string PinCode { get; set; } - } + [Option("pin", + Default = "0000", + HelpText = "pin code to provide to a device if it requires it for pairing")] + public string PinCode { get; set; } +} - internal static class PairDeviceByMac +internal static class PairDeviceByMac +{ + public static void Execute(PairDeviceByMacOptions opts) { - public static void Execute(PairDeviceByMacOptions opts) - { - var mac = new DeviceMacAddress(opts.Mac); - var device = DeviceFinder.FindDevicesByMac(mac, opts.DeviceType); - DevicePairer.PairDevice(device, opts.PinCode); - } + var mac = new DeviceMacAddress(opts.Mac); + var device = DeviceFinder.FindDevicesByMac(mac, opts.DeviceType); + DevicePairer.PairDevice(device, opts.PinCode); } } diff --git a/src/Commands/PairDeviceByName.cs b/src/Commands/PairDeviceByName.cs index 71b3e38..01bb7e1 100644 --- a/src/Commands/PairDeviceByName.cs +++ b/src/Commands/PairDeviceByName.cs @@ -3,38 +3,37 @@ using CommandLine; using System; -namespace BluetoothDevicePairing.Commands +namespace BluetoothDevicePairing.Commands; + +[Verb("pair-by-name", + HelpText = "Pair a device using its name.")] +internal sealed class PairDeviceByNameOptions : PairAndUnpairDeviceByNameOptions { - [Verb("pair-by-name", - HelpText = "Pair a device using its name.")] - internal sealed class PairDeviceByNameOptions : PairAndUnpairDeviceByNameOptions - { - [Option("pin", - Default = "0000", - HelpText = "pin code to provide to a device if it requires it for pairing")] - public string PinCode { get; set; } - } + [Option("pin", + Default = "0000", + HelpText = "pin code to provide to a device if it requires it for pairing")] + public string PinCode { get; set; } +} - internal static class PairDeviceByName +internal static class PairDeviceByName +{ + public static void Execute(PairDeviceByNameOptions opts) { - public static void Execute(PairDeviceByNameOptions opts) - { - var devices = DeviceFinder.FindDevicesByName(new DiscoveryTime(opts.DiscoveryTime), opts.DeviceName, opts.DeviceType); + var devices = DeviceFinder.FindDevicesByName(DeviceDiscoverer.DiscoverBluetoothDevices(new DiscoveryTime(opts.DiscoveryTime)), + opts.DeviceName, + opts.DeviceType); - if (devices.Count == 1) - { + switch (devices.Count) + { + case 1: DevicePairer.PairDevice(devices[0], opts.PinCode); return; - } - - if (devices.Count == 2) - { + case 2: throw new Exception( $"2 devices with the name '{opts.DeviceName}' found \n 1 - \"{devices[0]}\" \n 2 - \"{devices[1]}\". Don't know which one to choose."); - } - - throw new Exception( - $"{devices.Count} devices with the name '{opts.DeviceName}' found. Don't know which one to choose"); + default: + throw new Exception( + $"{devices.Count} devices with the name '{opts.DeviceName}' found. Don't know which one to choose"); } } } diff --git a/src/Commands/UnPairDeviceByMac.cs b/src/Commands/UnPairDeviceByMac.cs index 8054898..6315315 100644 --- a/src/Commands/UnPairDeviceByMac.cs +++ b/src/Commands/UnPairDeviceByMac.cs @@ -2,20 +2,19 @@ using BluetoothDevicePairing.Commands.Utils; using CommandLine; -namespace BluetoothDevicePairing.Commands +namespace BluetoothDevicePairing.Commands; + +[Verb("unpair-by-mac", HelpText = "Unpair a device using its mac address")] +internal sealed class UnpairDeviceByMacOptions : MacAndDeviceTypeOptions { - [Verb("unpair-by-mac", HelpText = "Unpair a device using its mac address")] - internal sealed class UnpairDeviceByMacOptions : MacAndDeviceTypeOptions - { - } +} - internal static class UnPairDeviceByMac +internal static class UnPairDeviceByMac +{ + public static void Execute(UnpairDeviceByMacOptions opts) { - public static void Execute(UnpairDeviceByMacOptions opts) - { - var mac = new DeviceMacAddress(opts.Mac); - var device = DeviceFinder.FindDevicesByMac(mac, opts.DeviceType); - DeviceUnPairer.UnpairDevice(device); - } + var mac = new DeviceMacAddress(opts.Mac); + var device = DeviceFinder.FindDevicesByMac(mac, opts.DeviceType); + DeviceUnPairer.UnpairDevice(device); } } diff --git a/src/Commands/UnPairDeviceByName.cs b/src/Commands/UnPairDeviceByName.cs index 17cf5b9..7ece7d5 100644 --- a/src/Commands/UnPairDeviceByName.cs +++ b/src/Commands/UnPairDeviceByName.cs @@ -3,24 +3,25 @@ using CommandLine; using System; -namespace BluetoothDevicePairing.Commands +namespace BluetoothDevicePairing.Commands; + +[Verb("unpair-by-name", HelpText = "Unpair a device using its name")] +internal sealed class UnpairDeviceByNameOptions : PairAndUnpairDeviceByNameOptions { - [Verb("unpair-by-name", HelpText = "Unpair a device using its name")] - internal sealed class UnpairDeviceByNameOptions : PairAndUnpairDeviceByNameOptions - { - } +} - internal static class UnPairDeviceByName +internal static class UnPairDeviceByName +{ + public static void Execute(UnpairDeviceByNameOptions opts) { - public static void Execute(UnpairDeviceByNameOptions opts) + var devices = DeviceFinder.FindDevicesByName(DeviceDiscoverer.DiscoverPairedBluetoothDevices(new DiscoveryTime(opts.DiscoveryTime)), + opts.DeviceName, + opts.DeviceType); + if (devices.Count > 1) { - var devices = DeviceFinder.FindDevicesByName(new DiscoveryTime(opts.DiscoveryTime), opts.DeviceName, opts.DeviceType); - if (devices.Count > 1) - { - throw new Exception($"{devices.Count} devices found, don't know which one to choose"); - } - - DeviceUnPairer.UnpairDevice(devices[0]); + throw new Exception($"{devices.Count} devices found, don't know which one to choose"); } + + DeviceUnPairer.UnpairDevice(devices[0]); } } diff --git a/src/Commands/Utils/CommonOptions.cs b/src/Commands/Utils/CommonOptions.cs index 225f720..7d4ecfc 100644 --- a/src/Commands/Utils/CommonOptions.cs +++ b/src/Commands/Utils/CommonOptions.cs @@ -1,33 +1,32 @@ using CommandLine; -namespace BluetoothDevicePairing.Commands.Utils +namespace BluetoothDevicePairing.Commands.Utils; + +internal class DeviceTypeOption { - internal class DeviceTypeOption - { - [Option("type", - Required = true, - HelpText = "(case sensitive) type of a bluetooth device. Possible values: \"Bluetooth\", \"BluetoothLE\"")] - public Bluetooth.Devices.DeviceType DeviceType { get; set; } - } + [Option("type", + Required = true, + HelpText = "(case sensitive) type of a bluetooth device. Possible values: \"Bluetooth\", \"BluetoothLE\"")] + public Bluetooth.Devices.DeviceType DeviceType { get; set; } +} - internal class MacAndDeviceTypeOptions : DeviceTypeOption - { - [Option("mac", - Required = true, - HelpText = "mac address of a bluetooth device. For example: 12:34:56:78:9A:BC")] - public string Mac { get; set; } - } +internal class MacAndDeviceTypeOptions : DeviceTypeOption +{ + [Option("mac", + Required = true, + HelpText = "mac address of a bluetooth device. For example: 12:34:56:78:9A:BC")] + public string Mac { get; set; } +} - internal class PairAndUnpairDeviceByNameOptions : DeviceTypeOption - { - [Option("discovery-time", - Default = 10, - HelpText = "how long to search for devices. Units: seconds")] - public int DiscoveryTime { get; set; } +internal class PairAndUnpairDeviceByNameOptions : DeviceTypeOption +{ + [Option("discovery-time", + Default = 10, + HelpText = "how long to search for devices. Units: seconds")] + public int DiscoveryTime { get; set; } - [Option("name", - Required = true, - HelpText = "(case sensitive) name of a bluetooth device")] - public string DeviceName { get; set; } - } + [Option("name", + Required = true, + HelpText = "(case sensitive) name of a bluetooth device")] + public string DeviceName { get; set; } } diff --git a/src/Commands/Utils/DeviceFinder.cs b/src/Commands/Utils/DeviceFinder.cs index 72878c6..146ecb0 100644 --- a/src/Commands/Utils/DeviceFinder.cs +++ b/src/Commands/Utils/DeviceFinder.cs @@ -2,32 +2,26 @@ using System; using System.Collections.Generic; -namespace BluetoothDevicePairing.Commands.Utils +namespace BluetoothDevicePairing.Commands.Utils; + +internal static class DeviceFinder { - internal static class DeviceFinder + public static List FindDevicesByName(List devices, string name, DeviceType deviceType) { - public static List FindDevicesByName(DiscoveryTime time, string name, DeviceType deviceType) - { - var devices = DeviceDiscoverer.DiscoverBluetoothDevices(time); - var res = devices.FindAll(d => d.Name == name && deviceType == d.Id.DeviceType); - - if (res.Count == 0) - { - throw new Exception($"Couldn't find any devices with '{name}' name and device type '{deviceType}'"); - } - - return res; - } + var res = devices.FindAll(d => d.Name == name && deviceType == d.Id.DeviceType); + return res.Count == 0 + ? throw new Exception($"Couldn't find any devices with '{name}' name and device type '{deviceType}'") + : res; + } - public static Device FindDevicesByMac(DeviceMacAddress mac, DeviceType deviceType) + public static Device FindDevicesByMac(DeviceMacAddress mac, DeviceType deviceType) + { + if (deviceType == DeviceType.Bluetooth) { - if (deviceType == DeviceType.Bluetooth) - { - Console.WriteLine($"Create Bluetooth device using Mac:'{mac}'"); - return BluetoothDevice.FromMac(mac); - } - Console.WriteLine($"Create BluetoothLE device using Mac:'{mac}'"); - return BluetoothLeDevice.FromMac(mac); + Console.WriteLine($"Create Bluetooth device using Mac:'{mac}'"); + return BluetoothDevice.FromMac(mac); } + Console.WriteLine($"Create BluetoothLE device using Mac:'{mac}'"); + return BluetoothLeDevice.FromMac(mac); } } diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 9f1c866..72762df 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,7 +4,8 @@ $(BuildFolder)$(Configuration)\ $(BuildFolder)obj\$(MSBuildProjectName)\ latest - 5 + 9999 + latest true 0.0-dev diff --git a/src/Program.cs b/src/Program.cs index ea4f4d9..c98c8a1 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -2,38 +2,29 @@ using CommandLine; using System; -namespace BluetoothDevicePairing +static void ParseCommandLineAndExecuteActions(string[] args) { - internal static class Program - { - private static void ParseCommandLineAndExecuteActions(string[] args) - { - Parser.Default.ParseArguments(args) - .WithParsed(DiscoverDevices.Execute) - .WithParsed(PairDeviceByMac.Execute) - .WithParsed(PairDeviceByName.Execute) - .WithParsed(UnPairDeviceByMac.Execute) - .WithParsed(UnPairDeviceByName.Execute) - .WithParsed(ListAdapters.Execute); - } + _ = Parser.Default.ParseArguments(args) + .WithParsed(DiscoverDevices.Execute) + .WithParsed(PairDeviceByMac.Execute) + .WithParsed(PairDeviceByName.Execute) + .WithParsed(UnPairDeviceByMac.Execute) + .WithParsed(UnPairDeviceByName.Execute) + .WithParsed(ListAdapters.Execute); +} - private static int Main(string[] args) - { - try - { - ParseCommandLineAndExecuteActions(args); - return 0; - } - catch (Exception ex) - { - Console.WriteLine($"Failed: {ex.Message}"); - return -1; - } - } - } +try +{ + ParseCommandLineAndExecuteActions(args); + return 0; +} +catch (Exception ex) +{ + Console.WriteLine($"Failed: {ex.Message}"); + return -1; }