6

I'm using a DeviceWatcher to get the DeviceInformation for a paired Bluetooth device in a UWP app. I set the DeviceWatcher up like this

var requestedProperties = new string[] { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected" };
var deviceWatcher = DeviceInformation.CreateWatcher("(System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\")", requestedProperties, DeviceInformationKind.AssociationEndpoint); // ClassGuid = {e0cbf06c-cd8b-4647-bb8a-263b43f0f974} includes all Bluetooth devices
deviceWatcher.Added += DeviceWatcher_Added;
deviceWatcher.Updated += DeviceWatcher_Updated;
deviceWatcher.Start();

When the DeviceWatcher_Added event handler is called I check to see if the device is the one I am interested in by checking its name and that it offers the RfcommServiceId.SerialPort.Uuid service.

Once I have the DeviceInformation for the bluetooth device I am interested in how do I get the COM port for it? I can see it in the Device Manager, where it is listed as "Standard Serial over Bluetooth link (COM8)", but I cannot see how to get that "COM8" in UWP programmatically.

I've tried making the DeviceInformation into a SerialDevice, whereby I could then get SerialDevice.PortName (c.f. this answer) but my call to SerialDevice.FromIdAsync(deviceInfo.Id) fails with a System.Exception: The data is invalid.

(N.B. Some tantalizing answers, like this and this, use the Windows Management Intrumentation WMI functions but these are not available in UWP.)

dumbledad
  • 16,305
  • 23
  • 120
  • 273
  • How do you make sure the deviceInfo.Id is your device's id (COM8)? Can you show the complete code make this exception:`System.Exception: The data is invalid`? – Rita Han Jun 02 '17 at 07:49
  • The full code is [here](https://github.com/dumbledad/BluetoothCOMGleaner) – dumbledad Jun 06 '17 at 09:39
  • Given you already know `deviceInfo.Name`, wonder if you could get the `Id` from this? `(await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelector())).Single(di => di.Name == deviceInfo.Name).Id` – Justin XL Jun 06 '17 at 14:10
  • Based on [your device info](https://stackoverflow.com/questions/44306228/serialdevice-fromidasyncstring-id-timing-out?noredirect=1#comment75773049_44306228), bluetooth rfcomm is the right direction but why do you want "SerialDevice.PortName"? – Rita Han Jun 07 '17 at 03:27
  • So I can call an existing code library that relies on it. – dumbledad Jun 07 '17 at 09:55

1 Answers1

3

On another question Rita suggested looking at the Serial UART sample which helped me see a way to do this. I won't mark this as the answer for a while as it seems too indirect to be the canonical way.

Although I have the the DeviceInformation for the paired Bluetooth device in my UWP app I also need the list of SerialDevices so that I can match them up. Here's the resulting code.

public async Task<string> ComPort(DeviceInformation deviceInfo)
{
    var serialDevices = new Dictionary<string, SerialDevice>();
    var serialSelector = SerialDevice.GetDeviceSelector();
    var serialDeviceInformations = (await DeviceInformation.FindAllAsync(serialSelector)).ToList();
    var hostNames = NetworkInformation.GetHostNames().Select(hostName => hostName.DisplayName.ToUpper()).ToList(); // So we can ignore inbuilt ports
    foreach (var serialDeviceInformation in serialDeviceInformations)
    {
        if (hostNames.FirstOrDefault(hostName => hostName.StartsWith(serialDeviceInformation.Name.ToUpper())) == null)
        {
            try
            {
                var serialDevice = await SerialDevice.FromIdAsync(serialDeviceInformation.Id);
                if (serialDevice != null)
                {
                    serialDevices.Add(deviceInfo.Id, serialDevice);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.ToString());
            }
        }
    }
    // Example Bluetooth DeviceInfo.Id: "Bluetooth#Bluetooth9c:b6:d0:d6:d7:56-00:07:80:cb:56:6d"
    // from device with Association Endpoint Address: "00:07:80:cb:56:6d"
    var lengthOfTrailingAssociationEndpointAddresss = (2 * 6) + 5;
    var bluetoothDeviceAddress = deviceInfo.Id.Substring(deviceInfo.Id.Length - lengthOfTrailingAssociationEndpointAddresss, lengthOfTrailingAssociationEndpointAddresss).Replace(":", "").ToUpper();
    var matchingKey = serialDevices.Keys.FirstOrDefault(id => id.Contains(bluetoothDeviceAddress));
    if (matchingKey != null)
    {
        return serialDevices[matchingKey].PortName;
    }
    return "";
}
dumbledad
  • 16,305
  • 23
  • 120
  • 273