Подтвердить что ты не робот

Как узнать номер COM-порта Bluetooth-устройства в С#?

Моя компания разработала устройство, которое взаимодействует с ПК через Bluetooth с помощью виртуального COM-порта.

Теперь нам нужно сначала подключить устройство с ПК (MS Windows OS), а затем ввести его номер COM-порта вручную в наше приложение (я уверен, что 95% пользователей потерпят неудачу на этих taks).

Поэтому я хотел бы, чтобы мое приложение представило пользователю список парных Bluetooth-устройств (список их "дружественных имен" ), после чего я хотел бы автоматически узнать номер COM-порта выбранного устройства.

Как я могу сделать это в С#? (оценивается решение, не зависящее от установленного пакета bluetooth).

Спасибо заранее.

4b9b3361

Ответ 1

См. мой ответ на Widcomm bluetooth: как открыть виртуальный COM для моего понимания лицензии: использование двоичной версии является бесплатным для коммерческого использования. И также, что я поддерживаю библиотеку.

Итак, небольшое небольшое отступление. Я не большой поклонник виртуальных COM-портов. Мне кажется, гораздо проще использовать прямое соединение "сокетов", а не пытаться настроить COM-порт и попытаться найти, какое имя оно было создано (см. Ниже!), А затем открыть SerialPort, чтобы использовать его, а затем, если соединение потеряно, никто не знает и просто пытается повторить попытку... С библиотекой гораздо проще просто создать и использовать это прямое соединение Bluetooth!

Однако вам может понадобиться решение вашей текущей задачи на данный момент.:-) Итак, используйте WMI, чтобы найти текущие COM-порты на месте и посмотреть, есть ли они для вашего устройства. Например, в PowerShell:

C:\> Get-WmiObject -query "select DeviceID,PNPDeviceID from Win32_SerialPort"
...
...
DeviceID         : COM66
PNPDeviceID      : BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}\7&1D80ECD3&0&00803A686519_C00000003

В этой большой длинной строке вы видите адрес целевого устройства: 00803A686519. Можно использовать WMI из .NET, выполнить этот запрос, отфильтровать те, что есть с "BTHENUM", а затем проанализировать адрес.

Если вам нужно создать новый виртуальный COM-порт Bluetooth, используйте API 32feet.NET BluetoothDeviceInfo.SetServiceState(BluetoothService.SerialPort). См. Раздел "Последовательные порты Bluetooth" в Руководстве пользователя, например. в http://www.alanjmcf.me.uk/comms/bluetooth/32feet.NET%20--%20User%20Guide.html и документация класса в релизе.

К сожалению, собственный API Win32, который мы вызываем, не указывает, какое имя COM-порта он создал!:-( Поэтому запустите запрос WMI до и после вызова, чтобы узнать, какое новое имя появилось (или используйте System.IO.Ports.SerialPort.GetPortNames как его более простой).

Это все зависит от стека Microsoft Bluetooth. Я не исследовал, как ведут себя другие стеки в этом отношении. После короткой проверки последовательные порты Widcomm отображаются в SerialPort.GetPortNames, но не в запросе WMI...

Ответ 2

Во-первых, создайте Searcher объекта управления для поиска в базе данных WMI:

ManagementObjectSearcher serialSearcher =
                new ManagementObjectSearcher("root\\CIMV2",
                "SELECT * FROM Win32_SerialPort");

Далее, используйте LINQ, чтобы получить все последовательные порты в запросе:

var query = from ManagementObject s in serialSearcher.Get()
            select new { Name = s["Name"], DeviceID = s["DeviceID"], PNPDeviceID = s["PNPDeviceID"] }; // DeviceID -- > PNPDeviceID

Теперь вы можете распечатать все COM-порты, их дружественные имена, и вы можете даже фильтровать через свой PNPDeviceID, чтобы найти адрес устройства Bluetooth. Вот пример:

foreach (var port in query)
{
    Console.WriteLine("{0} - {1}", port.DeviceID, port.Name);
    var pnpDeviceId = port.PNPDeviceID.ToString();

    if(pnpDeviceId.Contains("BTHENUM"))
    {
        var bluetoothDeviceAddress = pnpDeviceId.Split('&')[4].Split('_')[0];
        if (bluetoothDeviceAddress.Length == 12 && bluetoothDeviceAddress != "000000000000")
        {
            Console.WriteLine(" - Address: {0}", bluetoothDeviceAddress);
        }
    }
}

Ответ 3

Возможно, это не то, что вы ищете, и, возможно, вы уже нашли свой ответ...

Я только что нашел вопрос не так, как ваш, но работал у меня. С помощью этого вы можете узнать, какой из ваших COM-портов находится на устройстве Bluetooth: fooobar.com/questions/424102/...

Я надеюсь, что это поможет. Если вы узнаете, как сделать то, что вы хотели, сообщите мне. Спасибо.

Ответ 4

Мне удалось получить имя Bluetooth и COM-порт, вставив раздел реестра

Псевдокод для получения информации о bluetooth приведен ниже:

  • перечислить весь COM-порт, доступный в PNP
  • получить класс deviceGuid
  • найдите адрес Bluetooth из классаGuid
  • Когда адрес Bluetooth известен, имя Bluetooth можно получить из этого реестра SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices

Ниже приведен код, просто вызовите GetBluetoothPort(), он вернет список устройств bluetooth, и вы можете подключить их, передав номер COM-порта классу SerialPort

public static string[] GetBluetoothPort()
{
    Regex regexPortName = new Regex(@"(COM\d+)");

    List<string> portList = new List<string>();

    ManagementObjectSearcher searchSerial = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity");

    foreach (ManagementObject obj in searchSerial.Get()) {
        string name = obj["Name"] as string;
        string classGuid = obj["ClassGuid"] as string;
        string deviceID = obj["DeviceID"] as string;

        if (classGuid != null && deviceID != null) {
            if (String.Equals(classGuid, "{4d36e978-e325-11ce-bfc1-08002be10318}", StringComparison.InvariantCulture)) {
                string[] tokens = deviceID.Split('&');

                if (tokens.Length >= 4) {
                    string[] addressToken = tokens[4].Split('_');
                    string bluetoothAddress = addressToken[0];

                    Match m = regexPortName.Match(name);
                    string comPortNumber = "";
                    if (m.Success) {
                        comPortNumber = m.Groups[1].ToString();
                    }

                    if (Convert.ToUInt64(bluetoothAddress, 16) > 0) {
                        string bluetoothName = GetBluetoothRegistryName(bluetoothAddress);
                        portList.Add(String.Format("{0} {1} ({2})", bluetoothName, bluetoothAddress, comPortNumber));
                    }
                }
            }                    
        }
    }

    return portList.ToArray();
}

private static string GetBluetoothRegistryName(string address)
{
    string deviceName = "";

    string registryPath = @"SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices";
    string devicePath = String.Format(@"{0}\{1}", registryPath, address);

    using (RegistryKey key = Registry.LocalMachine.OpenSubKey(devicePath)) {
        if (key != null) {
            Object o = key.GetValue("Name");

            byte[] raw = o as byte[];

            if (raw != null) {
                deviceName = Encoding.ASCII.GetString(raw);
            }
        }
    }

    return deviceName;
}

Ответ 5

Итак, чтобы получить информацию о удаленном устройстве, включая его имя, используя 32feet.NET:

BluetoothAddress addr = ... ...
BluetoothDeviceInfo info = new BluetoothDeviceInfo(addr);
string name = info.DeviceName;

Если вы не используете библиотеку, вам придется P/Invoke Win32 BluetoothGetDeviceInfo.

Ответ 6

    private static string FindSerialPortForRFIDReaderCore()
    {
        string serialPort = "";

        List<string> ports = new List<string>();

        System.Management.ManagementObjectSearcher Searcher = new System.Management.ManagementObjectSearcher("Select * from WIN32_SerialPort");

        foreach (System.Management.ManagementObject Port in Searcher.Get())
        {
            if (Port["PNPDeviceID"].ToString().ToUpper().Contains("MacAddress")) 
                ports.Add(Port["DeviceID"].ToString());
        }

        if (ports.Count > 1) // There are more than one Serial Ports created for the bluetooth device.
            serialPort = ports.OrderByDescending(p => p).FirstOrDefault();
        else if(ports.Count == 1)
            serialPort = ports[0];


        return serialPort;
    }