Skip to content

Commit

Permalink
* Only consider paired devices when unpair devices by name
Browse files Browse the repository at this point in the history
* Improve code quality
  • Loading branch information
PolarGoose committed Mar 27, 2022
1 parent cba8a5c commit e9bf3c0
Show file tree
Hide file tree
Showing 26 changed files with 522 additions and 568 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/build/
.vs/
/src/FodyWeavers.xsd
/.idea
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
44 changes: 21 additions & 23 deletions src/Bluetooth/Adapters/Adapter.cs
Original file line number Diff line number Diff line change
@@ -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}'";
}
}
40 changes: 17 additions & 23 deletions src/Bluetooth/Adapters/AdapterFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Adapter> FindBluetoothAdapters()
{
public static Adapter FindDefaultAdapter()
{
return FindBluetoothAdapters().Where(adapter => adapter.IsDefault).Single();
}

public static IEnumerable<Adapter> 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();
}
}
15 changes: 7 additions & 8 deletions src/Bluetooth/Adapters/AdapterMacAddress.cs
Original file line number Diff line number Diff line change
@@ -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)
{
}
}
33 changes: 16 additions & 17 deletions src/Bluetooth/Devices/BluetoothDevice.cs
Original file line number Diff line number Diff line change
@@ -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());
}
}
41 changes: 19 additions & 22 deletions src/Bluetooth/Devices/BluetoothLeDevice.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
67 changes: 33 additions & 34 deletions src/Bluetooth/Devices/Device.cs
Original file line number Diff line number Diff line change
@@ -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}'";
}
}
69 changes: 34 additions & 35 deletions src/Bluetooth/Devices/DeviceDiscoverer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Device> DiscoverBluetoothDevices(DiscoveryTime time)
{
public static List<Device> DiscoverBluetoothDevices(DiscoveryTime time)
{
return Discover(AsqFilter.BluetoothDevicesFilter(), time);
}
return Discover(AsqFilter.BluetoothDevicesFilter(), time);
}

public static List<Device> DiscoverPairedBluetoothDevices(DiscoveryTime time)
{
return Discover(AsqFilter.PairedBluetoothDevicesFilter(), time);
}
public static List<Device> DiscoverPairedBluetoothDevices(DiscoveryTime time)
{
return Discover(AsqFilter.PairedBluetoothDevicesFilter(), time);
}

private static List<Device> Discover(AsqFilter filter, DiscoveryTime time)
{
Console.WriteLine($"Start discovering devices for {time.Seconds} seconds");
private static List<Device> 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);
}
}
Loading

0 comments on commit e9bf3c0

Please sign in to comment.