蓝牙的应用十分广泛,基于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();
}
代码1
SetRadioMode检查本端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);
代码2
Wince里面没有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();
}
代码3
Windows 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";
const
string
BT_DEVICE_KEY_NAME
=
"
Software\\Microsoft\\Bluetooth\\Device\\pan
"
;
//
wince 5
代码4
在wince下,注册表的位置取决于配对设备的类型,见下图。
图1
不同类型的配对设备放在不同的目录下。
但是在Windows Mobile下,所有配对信息存放于Software\\Microsoft\\Bluetooth\\Device下。
图2
ConnectService()的功能是链接服务端的设备。链接前同样选择串口服务,服务端和客户端需要使用统一的服务类型才能通信。在例子中连接后从服务端接收欢迎信息,然后不断往服务端发送数据。
从上面的例子看Windows Embedded Source Tools for Bluetooth的功能不是很完整,没有自动发现功能,也就是通信双方在通信之前需要配对成功,因此这样很不方便。而且Windows Embedded Source Tools for Bluetooth只是支持 Microsoft windows stack,不支持broadcom stack,后面文章会介绍另外一个的开源库32feet.NET。这个库支持自发现功能,同时部分支持broadcom stack。
转载 没有测试