博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows Moible, Wince 使用.NET Compact Framework的进行蓝牙(Bluetooth)广播程序的开发
阅读量:5172 次
发布时间:2019-06-13

本文共 5548 字,大约阅读时间需要 18 分钟。

简述

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

背景

在 的反馈中 同学希望实现蓝牙广播的功能,本文就是一个基于32feet.NET蓝牙广播的实现。

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

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

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

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

什么是广播

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

 

实现

服务端

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

成员定义

private BluetoothListener listener; private bool listening = true; private List
clientList = new List
(); 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
tempClientList = new List
(); 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.");

由于当前版本的32feet.net在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线程挂死。

 

源代码:

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

转载于:https://www.cnblogs.com/procoder/archive/2009/07/16/Windows_Mobile_Bluetooth_Broadcast.html

你可能感兴趣的文章
一些命令及参数
查看>>
Bootstrap validation
查看>>
2017.4.18-morning
查看>>
<MySQL学习十四>创建和操纵表
查看>>
Project Euler Problem 28
查看>>
ACE6.3.3在Linux(CentOS7.0)下的安装和使用
查看>>
面试准备
查看>>
mysql 1067
查看>>
java之接口适配器
查看>>
nginx安装手册
查看>>
动态将ASPX生成HTML网页并将网页导出PDF
查看>>
Find Backpacker Jobs in Australia
查看>>
面试题:return和finally执行
查看>>
Heroku第三方服务接入指南(二)
查看>>
MSRA专访摘要
查看>>
团队作业4
查看>>
随手一写,简单的四则运算练习
查看>>
DualGan
查看>>
Burp Suite详细使用教程-Intruder模块详3
查看>>
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
查看>>