我公司开发了一种使用虚拟COM端口通过蓝牙与PC通信的设备。
现在我们需要用户首先将设备与PC(MS Windows操作系统)配对,然后手动输入它的com端口号到我们的应用程序中(我敢打赌,95%的用户会因此而失败)。
所以我希望我的应用程序向用户显示配对的蓝牙设备列表(他们的“友好名称”列表),之后我想自动找出被选中的设备的COM端口号。 / p>
我怎样才能在c#中做到这一点? (非常感谢安装蓝牙堆栈的解决方案。)
提前致谢。
答案 0 :(得分:9)
请参阅我在Widcomm bluetooth : how to open the virtual COM的答案以了解我对许可的理解:使用二进制版本是免费的商业用途。而且,我也是图书馆的维护者。
这是一个简短的小题外话。我不是虚拟COM端口的忠实粉丝。使用直接'套接字'连接似乎要容易得多,而不是尝试设置COM端口,并尝试找到它创建的名称(见下文!),然后必须打开一个SerialPort才能使用它,然后,如果连接丢失,则不知道并且只是继续重试...使用库可以更容易地创建和使用直接蓝牙连接!
但是,您现在可能想要解决当前任务。 :-)因此,使用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。可以使用.NET中的WMI,运行该查询,使用“BTHENUM”过滤那些查询,然后解析出地址。
如果您确实需要创建新的蓝牙虚拟COM端口,请使用32feet.NET的BluetoothDeviceInfo.SetServiceState(BluetoothService.SerialPort)API。请参阅“用户指南”中的“蓝牙串行端口”部分,例如在http://www.alanjmcf.me.uk/comms/bluetooth/32feet.NET%20--%20User%20Guide.html,以及发布中的类文档。
不幸的是,我们调用的本机Win32 API并没有告诉它创建的COM端口的名称! :-(因此,在调用之前和之后运行WMI查询以查看出现的新名称(或使用System.IO.Ports.SerialPort.GetPortNames作为其更简单)。
这些都是微软蓝牙堆栈特有的。我还没有研究过其他堆栈在这方面的表现。经过简单检查后,Widcomm的串口出现在SerialPort.GetPortNames中,但不出现在WMI查询中......
答案 1 :(得分:4)
首先,创建一个管理对象搜索器来搜索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过滤来查找蓝牙设备地址。这是一个例子:
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);
}
}
}
答案 2 :(得分:2)
我设法通过摆弄注册表项来获取蓝牙名称和COM端口
获取蓝牙信息的伪代码如下:
SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices
代码如下,只需调用GetBluetoothPort(),它将返回蓝牙设备列表,您可以通过将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;
}
答案 3 :(得分:1)
也许这不是你想要的,也许你已经找到了答案......
我刚发现一个与你不完全相同的问题,但为我工作..有了这个,你可以找到你的哪个COM端口来自蓝牙设备: StackOverflow - Determine if serial port is normal COM or SPP
我希望它有所帮助。如果您发现如何做您想做的事,请告诉我。感谢。
答案 4 :(得分:0)
因此,要获取有关远程设备的信息,包括其名称,请使用32feet.NET执行:
BluetoothAddress addr = ... ...
BluetoothDeviceInfo info = new BluetoothDeviceInfo(addr);
string name = info.DeviceName;
如果不使用该库,您将需要P / Invoke Win32的BluetoothGetDeviceInfo。
答案 5 :(得分:0)
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;
}