600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Windows Moible Wince 使用.NET Compact Framework的进行蓝牙(Bluetooth)广播程序的开发

Windows Moible Wince 使用.NET Compact Framework的进行蓝牙(Bluetooth)广播程序的开发

时间:2022-04-29 04:43:48

相关推荐

Windows Moible  Wince 使用.NET Compact Framework的进行蓝牙(Bluetooth)广播程序的开发

简述

本文讲述如何使用实现Bluetooth的广播程序,同时演示了Broadcom stack在Windows Mobilie下的实现。

背景

在.NET Compact Framework下的Bluetooth开发 之 的反馈中 camper9999 同学希望实现蓝牙广播的功能,本文就是一个基于蓝牙广播的实现。

sammylp 的提出代码挂死问题,其实是使用过程的不恰当造成的,本文演示如何使用线程防止UI线程的挂起,程序的假死。

另外一个同学(不好意思忘记哪位了)问是否支持Broadcom stack,所以本文的实现运行于安装Broadcom stack的windows mobile中。

感谢各位的反馈,现在尽量在一篇文章中回答。

关于Bluetooth开发的也可以参考以下其他文章:

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

.NET Compact Framework下的Bluetooth开发 之

.NET Compact Framework下的Bluetooth开发 之 Bluetooth Virtual Serial Port

.NET Compact Framework下的Bluetooth设备的配对

30 Days of .NET [Windows Mobile Applications] - Day 02: Bluetooth Manager(蓝牙管理器)

什么是广播

所谓广播就是消息发送方向公众(public)发送信息的过程,广播有一个主要的特点是消息发送方不需要知道消息接收方的存在。现实生活中广播的例子如收音机广播,GPS卫星广播,以太网同网段数据包的广播等等。可是所谓蓝牙广播其实不算严格下的广播,因为蓝牙通信过程中有发现,配对,甚至验证过程,所以通信双方是需要握手的,没办法实现严格意义上的广播。本文例子实现了一个通过注册订阅方式的组播过程(MultiCast)。

实现

服务端

服务端负责监听和注册服务,同时把消息发送到已经注册的设备去。在例子中服务端使用PC实现,其实可以使用Windows Mobilie作为服务端,库基本兼容PC和CE。

成员定义

private BluetoothListener listener;

private bool listening = true;

private List<BluetoothClient> clientList = new List<BluetoothClient>();

private System.Threading.Thread listenThread;

private System.Threading.Thread broadcastThread;

listener负责监听服务,clientList 存放已经注册的设备,listenThread负责监听的线程,broadcastThread负责广播的线程。

启动服务

BluetoothRadio radio = BluetoothRadio.PrimaryRadio;

if (radio == null)

{

WriteMessage("No radio hardware or unsupported software stack");

return;

}

// Enable discoverable mode

radio.Mode = RadioMode.Discoverable;

WriteMessage("Radio Name:" + radio.Name);

WriteMessage("Radio Address:" + radio.LocalAddress);

WriteMessage("Radio Mode now: " + radio.Mode.ToString());

listener = new BluetoothListener(BluetoothService.SerialPort);

listener.Start();

listening = true;

listenThread = new System.Threading.Thread(ListenLoop);

broadcastThread = new System.Threading.Thread(BroadcastLoop);

listenThread.Start();

broadcastThread.Start();

WriteMessage("Service started!");

启动服务的流程是:

1.检查蓝牙设备是否准备好。

2.设置蓝牙设备为可发现。

3.启动蓝牙监听,这里配置的服务类型为串口服务,在客户端也需要配置串口服务类型才能进行通信。

4.启动监听线程,这样不会挂死主线程(Main Thread)。

5.启动广播线程。

监听线程

private void ListenLoop()

{

byte[] buffer = new byte[4];

string dataToSend = "Thanks for subscription";

byte[] dataBuffer = System.Text.ASCIIEncoding.ASCII.GetBytes(dataToSend);

while (listening)

{

try

{

BluetoothClient client = listener.AcceptBluetoothClient();

WriteMessage("Get a subscription from " + client.RemoteMachineName);

clientList.Add(client);

System.IO.Stream ns = client.GetStream();

ns.Write(dataBuffer, 0, dataBuffer.Length);

}

catch

{

break;

}

}

listener.Stop();

}

监听线程负责处理监听订阅请求,并把订阅的设备增加到订阅列表中。AcceptBluetoothClient()会挂起改线程,直到有新的设备进行订阅。

广播线程

private void BroadcastLoop()

{

List<BluetoothClient> tempClientList = new List<BluetoothClient>();

while (listening)

{

System.Threading.Thread.Sleep(5000);

string dataToSend = "Broadcast Message at " + System.DateTime.Now.ToLongTimeString();

byte[] dataBuffer = System.Text.ASCIIEncoding.ASCII.GetBytes(dataToSend);

tempClientList.Clear();

foreach (BluetoothClient client in clientList)

{

try

{

System.IO.Stream ns = client.GetStream();

ns.Write(dataBuffer, 0, dataBuffer.Length);

WriteMessage("Sent message to " + client.RemoteMachineName);

}

catch

{

//connection is broken.

tempClientList.Add(client);

continue;

}

}

//clean up the broken connections.

foreach (BluetoothClient client in tempClientList)

{

clientList.Remove(client);

}

}

}

广播线程负责对已经订阅的设备进行消息广播,同时管理已经断开的链接。在实际应用中,这个线程需要根据需求来更改业务流程。

关闭服务

WriteMessage("Service stop!");

listening = false;

if (listener != null)

{

listener.Stop();

}

释放监听资源。

UI处理

由于使用了多线程,不能直接更新UI,所以需要借助delegate和Invoke()函数来更新。

public delegate void SafeWinFormsThreadDelegate(string msg);

private void WriteMessage(string msg)

{

SafeWinFormsThreadDelegate d = new SafeWinFormsThreadDelegate(UpdateUi);

Invoke(d, new object[] { msg });

}

private void UpdateUi(string msg)

{

if (listBoxMsg.Items.Count > 100)

{

listBoxMsg.Items.RemoveAt(0);

}

listBoxMsg.SelectedIndex = listBoxMsg.Items.Add(msg);

}

客户端

客户端负责发现服务端设备,同时发起订阅请求,然后接收广播消息。客户端使用安装了BroadCom stack的Windows Mobile实现,实际上同时支持MS stack。

发现

BluetoothRadio radio = BluetoothRadio.PrimaryRadio;

if (radio == null)

{

WriteMessage("No radio hardware or unsupported software stack");

return;

}

//Broadcom stack doesn't support the functionality to turn on the bluetooth, turn it on manually please

//radio.Mode = RadioMode.Connectable;

//Scan the nearby devices

listBoxDevices.Items.Clear();

BluetoothDeviceInfo[] devices = client.DiscoverDevices();

listBoxDevices.DataSource = devices;

listBoxDevices.DisplayMember = "DeviceName";

listBoxDevices.ValueMember = "DeviceAddress";

WriteMessage("Discover successful, please select one device to subscribe.");

由于当前版本的在BroadCom stack下不支持设置蓝牙状态,所以如果设备是BroadCom stack需要屏蔽设置蓝牙状态的语句。把发现到的设备显示到ListBox里面。

订阅

BluetoothAddress deviceAddress = listBoxDevices.SelectedValue as BluetoothAddress;

client.Connect(deviceAddress, BluetoothService.SerialPort);

WriteMessage("Connected to " + client.RemoteMachineName);

stream = client.GetStream();

receiving = true;

System.Threading.Thread t = new System.Threading.Thread(ReceiveLoop);

t.Start();

根据发现的服务端设备的地址进行连接,然后启动线程接收消息。

接收消息

private void ReceiveLoop()

{

byte[] buffer = new byte[255];

while (receiving)

{

if (stream.CanRead)

{

stream.Read(buffer, 0, 255);

string data = System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, 255);

WriteMessage(data);

}

}

}

在线程里接收消息,避免主UI线程挂死。

源代码:/procoder/BtBroadcast.rar

平台:Visual Studio + Windows Mobile 5 Packet PC SDK

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。