Bluetooth的应用十分广泛,基于Bluetooth的通信程序开发主要有以下几个步骤:服务端* 设置本设备为可发现。* 公开服务给其他Bluetooth设备访问。* 接受其他Bluetooth设备的链接。* 与链接上的Bluetooth设备进行通信。客户端* 发现周边Bluetooth设备。* 主动与被发现的设备发起连接。* 与链接上的Bluetooth设备进行通信。在.NET Compact Framework下进行Bluetooth开发有几个可选解决方案* 可以P/Invoke直接调用Bluetooth的API(btdrt.dll)* 使用MS的Windows Embedded Source Tools for Bluetooth* 使用32feet.NET库这篇文章讲述基于Windows Embedded Source Tools for Bluetooth的开发,点击 链接 下载Windows Embedded Source Tools for Bluetooth,安装后在目录 C:/Program Files/Microsoft/Windows Embedded Source Tools会找到源码以及编译后的DLL。服务端
using Microsoft.WindowsMobile.SharedSource.Bluetooth;private void SetRadioMode(){ BluetoothRadio br = new BluetoothRadio(); WriteMessage("Radio Mode:" + br.BluetoothRadioMode); if (br.BluetoothRadioMode != BluetoothRadioMode.Discoverable) { br.BluetoothRadioMode = BluetoothRadioMode.Discoverable; WriteMessage("Radio Mode:" + br.BluetoothRadioMode); }}private void StartService(){ Guid guid = StandardServices.SerialPortServiceGuid; service = new BluetoothService(guid); service.Start(); WriteMessage("Service started!"); System.Net.Sockets.NetworkStream ns = service.AcceptConnection(); //Warning: this is blocking code WriteMessage("Got a request!"); string dataToSend = "Hello from service!"; // Convert dataToSend into a byte array byte[] dataBuffer = System.Text.ASCIIEncoding.ASCII.GetBytes(dataToSend); // Output data to stream ns.Write(dataBuffer, 0, dataBuffer.Length); byte[] buffer = new byte[2000]; while (service.Started && !stop) { if (ns.DataAvailable) { ns.Read(buffer, 0, 50); string data = System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, 50); WriteMessage("Receiving data:" + data); } } // Clear and close stream ns.Flush(); ns.Close();} 复制代码代码1SetRadioMode检查本端Bluetooth设备是否为可发现,如果不可发现就设置为可发现。本地Bluetooth设备的状态分成三种:On,Off,Discoverable。在Windows Embedded Source Tools for Bluetooth库里面查询和设置设备RadioMode的函数有点问题,只能用在Windows Mobile里面,如果在Wince里使用,需要对SafeNativeMethods.cs进行以下的修改:
//It does not support Wince 5 since Wince 5 does not include bthutil.dll//[DllImport(BTHUTIL_DLL)]//public static extern int BthGetMode(ref BluetoothRadioMode mode);//[DllImport(BTHUTIL_DLL)]//public static extern int BthSetMode(BluetoothRadioMode mode);public static int BthGetMode(ref BluetoothRadioMode mode){ int mask = 0; int ret = BthReadScanEnableMask(ref mask); switch (mask) { case 0x0: mode = BluetoothRadioMode.Off; break; case 0x2: mode = BluetoothRadioMode.On; break; case 0x3: mode = BluetoothRadioMode.Discoverable; break; } return ret;}public static int BthSetMode(BluetoothRadioMode mode){ int mask = 0; switch (mode) { case BluetoothRadioMode.Off: mask = 0x0; break; case BluetoothRadioMode.On: mask = 0x2; break; case BluetoothRadioMode.Discoverable: mask = 0x3; break; } return BthWriteScanEnableMask(mask);}[DllImport(BTDRT_DLL)]public static extern int BthReadScanEnableMask(ref int mask);[DllImport(BTDRT_DLL)]public static extern int BthWriteScanEnableMask(int mask); 复制代码代码2Wince里面没有bthutil.dll,所以不能直接使用BthGetMode和BthSetMode的APIs了。需要调用BthReadScanEnableMask和BthWriteScanEnableMask来实现。StartService使用winsock启动一个服务的侦听,在启动服务端时候必须选择服务,例子里选择了串口服务。关于bluetooth的服务,可以参考 http://en.wikipedia.org/wiki/Bluetooth_profile。 注意当service启动后,使用service.AcceptConnection()会把线程挂起,如果在实际使用中,一般需要启动一个worker thread执行,否则程序没办法处理其他任务,例如UI的响应。传输的数据是比特串(byte[]),所以可以传输任意类型的数据,在例子中传输的数据为string。在例子中回应"Hello from service!"给客户端后开始不停的接收,实际通信顺序由具体需求决定。客户端
private void PairedDevices(){ BluetoothRadio br = new BluetoothRadio(); BluetoothDeviceCollection devices = br.PairedDevices; foreach (BluetoothDevice device in devices) { WriteMessage("ID:" + device.Address[5].ToString("X2") + "-" + device.Address[4].ToString("X2") + "-" + device.Address[3].ToString("X2") + "-" + device.Address[2].ToString("X2") + "-" + device.Address[1].ToString("X2") + "-" + device.Address[0].ToString("X2") + ", Name:" + device.Name); } ConnectService(devices[0] as BluetoothDevice);}private void ConnectService(BluetoothDevice device){ Guid guid = StandardServices.SerialPortServiceGuid; // Create network stream object // Connect to the device service (via the GUID) System.Net.Sockets.NetworkStream ns = device.Connect(guid); // Create storage for receiving data byte[] buffer = new byte[2000]; // Read Data ns.Read(buffer, 0, 50); // Convert Data to String string data = System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, 50); WriteMessage("Receiving data: " + data); int i = 0; while (!stop) { WriteMessage("Writing: " + i.ToString()); byte[] dataBuffer = System.Text.ASCIIEncoding.ASCII.GetBytes(i.ToString()); ns.Write(dataBuffer, 0, dataBuffer.Length); ++i; if (i >= int.MaxValue) { i = 0; } System.Threading.Thread.Sleep(500); } // Close network stream ns.Close();} 复制代码代码3Windows Embedded Source Tools for Bluetooth不支持自发现功能,所以在客户端的设备首先要和服务端的设备进行配对,所谓配对就是把对端的信息写入注册表里面。PairedDevices()取出配对信息,其实就是从注册表里面取信息,Windows Embedded Source Tools for Bluetooth这个功能也写得不好,如果在wince下使用需要修改BluetoothRadio.cs文件的PairedDevices属性。//const string BT_DEVICE_KEY_NAME = "Software//Microsoft//Bluetooth//Device";conststring BT_DEVICE_KEY_NAME ="Software//Microsoft//Bluetooth//Device//pan"; //wince 5代码4在wince下,注册表的位置取决于配对设备的类型,见下图。图1不同类型的配对设备放在不同的目录下。但是在Windows Mobile下,所有配对信息存放于Software//Microsoft//Bluetooth//Device下。图2ConnectService()的功能是链接服务端的设备。链接前同样选择串口服务,服务端和客户端需要使用统一的服务类型才能通信。在例子中连接后从服务端接收欢迎信息,然后不断往服务端发送数据。从上面的例子看Windows Embedded Source Tools for Bluetooth的功能不是很完整,没有自动发现功能,也就是通信双方在通信之前需要配对成功,因此这样很不方便。而且Windows Embedded Source Tools for Bluetooth只是支持 Microsoft windows stack,不支持broadcom stack,后面文章会介绍另外一个的开源库32feet.NET。这个库支持自发现功能,同时部分支持broadcom stack。