-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add "list-adapters" command line option * Use a BluetoothDevice.FromBluetoothAddressAsync method for discovering a device by mac address. It is simpler than using previously implemented approach.
- Loading branch information
1 parent
d086e5c
commit 9b8473a
Showing
23 changed files
with
251 additions
and
217 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,13 @@ | ||
using System; | ||
using System.Linq; | ||
using Windows.Devices.Bluetooth; | ||
|
||
namespace BluetoothDevicePairing.Bluetooth.Adapter | ||
{ | ||
internal sealed class AdapterMacAddress : IEquatable<AdapterMacAddress> | ||
internal sealed class AdapterMacAddress : MacAddress | ||
{ | ||
public string Address { get; } | ||
|
||
public AdapterMacAddress(BluetoothAdapter adapter) | ||
{ | ||
Address = string.Join(":", BitConverter.GetBytes(adapter.BluetoothAddress) | ||
.Reverse() | ||
.Skip(2) | ||
.Select(b => b.ToString("x2"))); | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
return Address; | ||
} | ||
|
||
public bool Equals(AdapterMacAddress other) | ||
{ | ||
if (other is null) | ||
{ | ||
return false; | ||
} | ||
|
||
if (ReferenceEquals(this, other)) | ||
{ | ||
return true; | ||
} | ||
|
||
return Address == other.Address; | ||
} | ||
|
||
public override bool Equals(object obj) | ||
public AdapterMacAddress(Windows.Devices.Bluetooth.BluetoothAdapter adapter) : base(adapter.BluetoothAddress) | ||
{ | ||
return ReferenceEquals(this, obj) || obj is AdapterMacAddress other && Equals(other); | ||
} | ||
|
||
public override int GetHashCode() | ||
public AdapterMacAddress(string mac) : base(mac) | ||
{ | ||
return Address != null ? Address.GetHashCode() : 0; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using System; | ||
|
||
namespace BluetoothDevicePairing.Bluetooth.Devices | ||
{ | ||
internal sealed class BluetoothDevice : Device | ||
{ | ||
public 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; | ||
} | ||
|
||
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()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
using System; | ||
|
||
namespace BluetoothDevicePairing.Bluetooth.Devices | ||
{ | ||
internal class BluetoothLeDevice : Device | ||
{ | ||
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; | ||
} | ||
|
||
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); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,79 +1,42 @@ | ||
using System; | ||
using System.Text.RegularExpressions; | ||
|
||
namespace BluetoothDevicePairing.Bluetooth.Devices | ||
{ | ||
internal enum ConnectionStatus | ||
{ | ||
NotPaired, | ||
Paired, | ||
Connected | ||
} | ||
|
||
internal enum DeviceType | ||
{ | ||
Bluetooth, | ||
BluetoothLE | ||
} | ||
|
||
internal sealed class Device | ||
internal abstract class Device | ||
{ | ||
private readonly Windows.Devices.Enumeration.DeviceInformation info; | ||
private readonly Windows.Devices.Bluetooth.BluetoothDevice bluetoothDevice; | ||
private readonly Windows.Devices.Bluetooth.BluetoothLEDevice bluetoothLeDevice; | ||
protected abstract bool IsConnected { get; } | ||
|
||
public string Id => info.Id; | ||
public ConnectionStatus ConnectionStatus => | ||
IsConnected | ||
? ConnectionStatus.Connected | ||
: PairingInfo.IsPaired | ||
? ConnectionStatus.Paired | ||
: ConnectionStatus.NotPaired; | ||
public Windows.Devices.Enumeration.DeviceInformationPairing PairingInfo => info.Pairing; | ||
public bool IsPaired => info.Pairing.IsPaired; | ||
public DeviceMacAddress Mac { get; } | ||
public DeviceType Type { get; } | ||
public DeviceInfoId Id { get; } | ||
public string Name => info.Name; | ||
public bool IsConnected | ||
{ | ||
get | ||
{ | ||
if (bluetoothDevice != null) | ||
{ | ||
return bluetoothDevice.ConnectionStatus == Windows.Devices.Bluetooth.BluetoothConnectionStatus.Connected; | ||
} | ||
else | ||
{ | ||
return bluetoothLeDevice.ConnectionStatus == Windows.Devices.Bluetooth.BluetoothConnectionStatus.Connected; | ||
} | ||
} | ||
} | ||
|
||
public Device(Windows.Devices.Enumeration.DeviceInformation info) | ||
protected Device(Windows.Devices.Enumeration.DeviceInformation info) | ||
{ | ||
this.info = info; | ||
Mac = new DeviceMacAddress(info); | ||
Type = GetDeviceType(info); | ||
if (Type == DeviceType.Bluetooth) | ||
{ | ||
bluetoothDevice = Windows.Devices.Bluetooth.BluetoothDevice.FromIdAsync(info.Id).GetAwaiter().GetResult(); | ||
} | ||
else | ||
{ | ||
bluetoothLeDevice = Windows.Devices.Bluetooth.BluetoothLEDevice.FromIdAsync(info.Id).GetAwaiter().GetResult(); | ||
} | ||
Id = new DeviceInfoId(info); | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
return $"name:'{Name}' mac:'{Mac}' type:'{Type}' Connected:'{IsConnected}' Paired:'{IsPaired}'"; | ||
} | ||
|
||
private static DeviceType GetDeviceType(Windows.Devices.Enumeration.DeviceInformation device) | ||
{ | ||
var match = Regex.Match(device.Id, @"(^\w*)(#)"); | ||
if (!match.Success) | ||
{ | ||
throw new Exception($"Failed to extract the device type from the string '{device.Id}'"); | ||
} | ||
|
||
var type = match.Groups[1].Value; | ||
switch (type) | ||
{ | ||
case "Bluetooth": | ||
return DeviceType.Bluetooth; | ||
case "BluetoothLE": | ||
return DeviceType.BluetoothLE; | ||
default: | ||
throw new Exception($"Wrong device type '{type}' extracted from '{device.Id}'"); | ||
} | ||
return $"name:'{Name}' mac:'{Id.DeviceMac}' type:'{Id.DeviceType}' ConnectionStatus:'{ConnectionStatus}'"; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,54 @@ | ||
using BluetoothDevicePairing.Bluetooth.Devices.Utils; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading; | ||
|
||
namespace BluetoothDevicePairing.Bluetooth.Devices | ||
{ | ||
internal static class DeviceDiscoverer | ||
internal class DiscoveryTime | ||
{ | ||
public static List<Device> DiscoverBluetoothDevices(int timeoutInSec) | ||
public int Seconds { get; } | ||
|
||
public DiscoveryTime(int timeInSeconds) | ||
{ | ||
return Discover(AsqFilter.BluetoothDevicesFilter(), timeoutInSec); | ||
if (timeInSeconds < 1 || timeInSeconds > 30) | ||
{ | ||
throw new Exception($"discovery time should be in range [1; 30] but was {timeInSeconds}"); | ||
} | ||
|
||
Seconds = timeInSeconds; | ||
} | ||
} | ||
|
||
public static List<Device> DiscoverPairedBluetoothDevices(int timeoutInSec) | ||
internal static class DeviceDiscoverer | ||
{ | ||
public static List<Device> DiscoverBluetoothDevices(DiscoveryTime time) | ||
{ | ||
return Discover(AsqFilter.PairedBluetoothDevicesFilter(), timeoutInSec); | ||
return Discover(AsqFilter.BluetoothDevicesFilter(), time); | ||
} | ||
|
||
private static List<Device> Discover(AsqFilter filter, int discoveryTimeInSec) | ||
public static List<Device> DiscoverPairedBluetoothDevices(DiscoveryTime time) | ||
{ | ||
Console.WriteLine($"Start discovering devices for {discoveryTimeInSec} seconds"); | ||
return Discover(AsqFilter.PairedBluetoothDevicesFilter(), time); | ||
} | ||
|
||
if (discoveryTimeInSec < 1 || discoveryTimeInSec > 30) | ||
{ | ||
throw new Exception($"discovery time should be in range [1; 30] but was {discoveryTimeInSec}"); | ||
} | ||
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(discoveryTimeInSec * 1000); | ||
Thread.Sleep(time.Seconds * 1000); | ||
var devices = watcher.Stop(); | ||
return devices.Select(d => new Device(d)).ToList(); | ||
return devices.Select(info => CreateDevice(info)).ToList(); | ||
} | ||
|
||
private static Device CreateDevice(Windows.Devices.Enumeration.DeviceInformation info) | ||
{ | ||
return new DeviceInfoId(info).DeviceType == DeviceType.Bluetooth | ||
? BluetoothDevice.FromDeviceInfo(info) | ||
: BluetoothLeDevice.FromDeviceInfo(info); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using BluetoothDevicePairing.Bluetooth.Adapter; | ||
using System; | ||
using System.Text.RegularExpressions; | ||
|
||
namespace BluetoothDevicePairing.Bluetooth.Devices | ||
{ | ||
internal sealed class DeviceInfoId | ||
{ | ||
public DeviceType DeviceType { get; } | ||
public AdapterMacAddress AdapterMac { get; } | ||
public DeviceMacAddress DeviceMac { get; } | ||
|
||
public DeviceInfoId(Windows.Devices.Enumeration.DeviceInformation info) | ||
{ | ||
var match = Regex.Match(info.Id, @"(^\w+)#(?<Type>Bluetooth|BluetoothLE)(?<AdapterMac>(..:){5}(..))-(?<DeviceMac>(..:){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); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,61 +1,9 @@ | ||
using System; | ||
using System.Text.RegularExpressions; | ||
using Windows.Devices.Enumeration; | ||
|
||
namespace BluetoothDevicePairing.Bluetooth.Devices | ||
{ | ||
internal sealed class DeviceMacAddress : IEquatable<DeviceMacAddress> | ||
internal sealed class DeviceMacAddress : MacAddress | ||
{ | ||
public DeviceMacAddress(DeviceInformation device) | ||
public DeviceMacAddress(string mac) : base(mac) | ||
{ | ||
var match = Regex.Match(device.Id, @"(..:){5}(..)$"); | ||
if (!match.Success) | ||
{ | ||
throw new Exception($"Failed to extract mac address from the string '{device.Id}'"); | ||
} | ||
Address = match.Value.ToUpper(); | ||
} | ||
|
||
public DeviceMacAddress(string mac) | ||
{ | ||
var match = Regex.Match(mac, @"^(..:){5}(..)$"); | ||
if (!match.Success) | ||
{ | ||
throw new Exception($"MacAddress address '{mac}' is not a valid mac address"); | ||
} | ||
Address = mac; | ||
} | ||
|
||
public string Address { get; } | ||
|
||
public override string ToString() | ||
{ | ||
return Address; | ||
} | ||
|
||
public bool Equals(DeviceMacAddress other) | ||
{ | ||
if (other is null) | ||
{ | ||
return false; | ||
} | ||
|
||
if (ReferenceEquals(this, other)) | ||
{ | ||
return true; | ||
} | ||
|
||
return Address == other.Address; | ||
} | ||
|
||
public override bool Equals(object obj) | ||
{ | ||
return ReferenceEquals(this, obj) || obj is DeviceMacAddress other && Equals(other); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return Address != null ? Address.GetHashCode() : 0; | ||
} | ||
} | ||
} |
Oops, something went wrong.