c# 蓝牙虚拟串口_Windows Moible, Wince 使用.NET Compact Framework的进行蓝牙(Bluetooth)开发 之 蓝牙虚拟串口 (Bluetooth Virtu...

本文介绍了蓝牙虚拟串口(Bluetooth Virtual Serial Port)开发。它将蓝牙通信转化为串口通信,以支持现有应用。MS不推荐新系统使用,建议用Winsock通信。还讲述了在Windows Mobile下建立蓝牙虚拟串口的两种方法:调用API和修改注册表,并给出了相关代码示例。

在之前的两篇文章分别讲述了在.NET Compact Framework下使用Windows Embedded Source Tools for Bluetooth和32feet.NET进行Bluetooth的开发,链接如下:

.NET Compact Framework下的Bluetooth开发 之 Windows Embedded Source Tools for Bluetooth

.NET Compact Framework下的Bluetooth开发 之 32feet.NET

在这篇文章讲述Bluetooth Virtual Serial Port的开发,所谓Bluetooth Virtual Serial Port,其实是从软件的角度看,把Bluetooth的通信转化成Serial Port(串口)。经过这样的转换后,使用Bluetooth的Client程序可以像使用串口一样操作Bluetooth。这个应用方式的出现是为了支持现有应用(Legacy system,遗产应用)。举个例子,在Bluetooth出现以前,大部分移动设备都是通过串口连接的GPS receiver的,基于GPS应用程序的开发也就通过的串口通信取出NMEA data。关于GPS NMEA data的开发可以参考 .NET Compact Framework下的GPS NMEA data数据分析 。串口的开发可以参考.NET Compact Framework下的串口通信。随着Bluetooth的普及,移动设备可以通过Bluetooth来连接GPS receiver了,那么原先基于GPS的应用程序需要重新开发通信部分去读取NMEA data,这为现有应用带来很多麻烦,所有的现有应用都需要重写通信部分,因此人们想出解决方法,把Bluetooth的通信转化成Serial Port(串口)。硬件上使用Bluetooth来进行通信,在软件上虚拟一个串口给应用程序,应用程序不需要任何的修改就可以支持Bluetooth的GPS Receiver了。这就像设计模式里面的Adapter模式,但是这里是为新设备提供原有的接口,使得原先的Client不需要更改。

由于Bluetooth Virtual Serial Port的出现基于对现有系统(Legacy System)支持的需求,所以对于新的系统,MS不推荐使用Bluetooth Virtual Serial Port,而是直接使用Winsock进行通信。在使用Winsock进行Bluetooth通信需要指定服务,因此可以指定使用串口服务进行通信。Bluetooth Virtual Serial Port和Winsock的Bluetooth通信都是使用RFCOMM协议,所以两者等同。使用Winsock的Bluetooth通信比Bluetooth Virtual Serial Port更简单,不需要配置。而且更强壮(robust),因为使用Winsock的Bluetooth通信可以直接监听到蓝牙设备关闭或者离开通信范围,而Bluetooth Virtual Serial Port只能通过Timeout来检查。

由于支持现有系统(Legacy System),Bluetooth Virtual Serial Port还是有存在的价值,下面讲述Bluetooth Virtual Serial Port的开发。在Windows Mobile下有两种方法可以建立Bluetooth Virtual Serial Port:调用API建立Bluetooth Virtual Serial Port和修改注册表建立Bluetooth Virtual Serial Port

调用API建立Bluetooth Virtual Serial Port

调用API建立Bluetooth Virtual Serial Port可以调用RegisterDevice

HANDLE h=RegisterDevice (L"COM", index, L"btd.dll", (DWORD)&pp);

建立服务端口,需要配置以下参数

PORTEMUPortParams pp;

memset (&pp,0,sizeof(pp));

pp.flocal=TRUE;

pp.channel=channel&0xff;

服务端口flocal为true。channel可以使用RFCOMM_CHANNEL_MULTIPLE (0xfe),这样RFCOMM 会自动分配可用的信道。

建立客户端口,需要配置以下参数

PORTEMUPortParams pp;

memset (&pp,0,sizeof(pp));

pp.device=ba;

pp.channel=channel&0xff;

服务端口flocal为false。device为服务端地址。

反注册端口使用以下API

DeregisterDevice (h);

详细可以参考MSDN文章 Creating a Connection to a Remote Device Using a Virtual COM Port,链接见参考文献。

在32feet.net里面,这些API封装在InTheHand.Net.Ports.BluetoothSerialPort,可以直接使用。但是32feet.net的作者提醒这些API是不是可信赖的(unreliable),所以在使用之前请要谨慎考虑和详细测试。我在wince 5下测试过,不能成功建立Bluetooth Virtual Serial Port。

使用32feet.net建立服务端口

publicstaticvoidCreateIncomingPort()

{

BluetoothSerialPort port=BluetoothSerialPort.CreateServer(BluetoothService.SerialPort);

Console.WriteLine(port.PortName);

}

使用32feet.net建立客户端口

publicstaticvoidCreateIncomingPort()

{

BluetoothClient client=newBluetoothClient();

BluetoothDeviceInfo[] devices=client.DiscoverDevices();

BluetoothDeviceInfo device=null;foreach(BluetoothDeviceInfo dindevices)

{if(d.DeviceName=="BLUETOOTH_DEVICE")

{

device=d;break;

}

}

BluetoothEndPoint  endPoint=newBluetoothEndPoint(device.DeviceAddress, BluetoothService.SerialPort);

BluetoothSerialPort port=BluetoothSerialPort.CreateClient(endPoint);

Console.WriteLine(port.PortName);

}

修改注册表建立Bluetooth Virtual Serial Port

由于第一种方法不是很可靠,所以可以选择第二种方法,第二种方法其实就是修改注册表,把

HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Bluetooth\\Serial\\Ports的项进行修改。可是这个方法只是支持windows mobile5以上的系统,不支持wince5。同时,如果使用这个方法,需要重启系统。

这是Windows Mobile的注册表,可以通过程序修改注册表的项目,通过程序修改后需要重启Windows Mobile。

上图为Wince 5的注册表,结构不一样,在Wince5不能通过修改注册表的方式实现Bluetooth Virtual Serial Port。

下面的代码来源自32feet.net的BluetoothDeviceInfo类里面的SetServiceState()方法。这里演示了如何修改注册表。

if(state)

{//write registry settings for WM5 Serial Port support//get available portsMicrosoft.Win32.RegistryKey rkPorts=Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Bluetooth\\Serial\\Ports",true);string[] supportedPorts=(string[])rkPorts.GetValue("SupportedPorts");

System.Collections.ArrayList alPorts=newSystem.Collections.ArrayList(supportedPorts);//check availabilityforeach(stringdeviceidinrkPorts.GetSubKeyNames())

{

Microsoft.Win32.RegistryKey rkDevice=rkPorts.OpenSubKey(deviceid);//remove port from arraylist if unavailablestringport=rkDevice.GetValue("Port").ToString();intnullPos=port.IndexOf('\0');if(nullPos>-1)

{

port=port.Substring(0, nullPos);

}if(alPorts.Contains(port))

{

alPorts.Remove(port);

}

rkDevice.Close();

}if(alPorts.Count==0)

{thrownewInvalidOperationException("No ports available");

}//write port details to registryMicrosoft.Win32.RegistryKey rkNewPort=rkPorts.CreateSubKey(this.DeviceAddress.ToString("8"));

rkNewPort.SetValue("KeepDCB",0);

rkNewPort.SetValue("RemoteDCB",0);

rkNewPort.SetValue("Encryption",0);

rkNewPort.SetValue("Authentication",0);

rkNewPort.SetValue("Port", alPorts[0]);

rkNewPort.SetValue("Server",0);

rkNewPort.Close();

rkPorts.Close();//try open port nowtry{

InTheHand.Net.Ports.BluetoothSerialPort.CreateClient(alPorts[0].ToString(),newBluetoothEndPoint(this.DeviceAddress, BluetoothService.SerialPort));

}catch{

}

}else{//find and remove registry entriesMicrosoft.Win32.RegistryKey rkPorts=Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Bluetooth\\Serial\\Ports",true);foreach(stringdeviceAddressinrkPorts.GetSubKeyNames())

{if(deviceAddress==this.DeviceAddress.ToString("8"))

{

rkPorts.DeleteSubKeyTree(deviceAddress);break;

}

}

rkPorts.Close();

}

当state为true时为注册,当state为false时为反注册。

参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值