利用ESP32来模拟BT蓝牙(BLE低功耗蓝牙后续也会进行测试)
C#利用32feet.NET库来实现蓝牙的使用。
(1)初始化扫描蓝牙设备写入选择框
(2)连接蓝牙设备,连接成功则开启监听线程
(3)监听线程接收到数据设置回调函数将接收到的内容显示在文本框上。
(4)点击发送按钮后将文本框的内容发送给接收端。
private async void Booth_Init() { try { client = new BluetoothClient(); // 使用 Task.Run 来在另一个线程中执行 DiscoverDevices devices = await Task.Run(() => client.DiscoverDevices()); BoothChoose.Items.Clear(); foreach (BluetoothDeviceInfo device in devices) { // 确保 UI 更新在 UI 线程上执行 this.Invoke((MethodInvoker)delegate { BoothChoose.Items.Add(device.DeviceName); }); Console.WriteLine(device.DeviceName); } // 确保在 UI 线程上修改 SelectedIndex this.Invoke((MethodInvoker)delegate { if (BoothChoose.Items.Count > 0) { BoothChoose.SelectedIndex = 0; } }); } catch (Exception ex) { Console.WriteLine("错误: " + ex.Message); } }
初始化的代码是使用异步的方式扫描设备,并且将设备名称显示在选择控件上,之所以是采用异步的方式原因是不采用异步会占用UI线程导致UI线程无法使用。所以需要单独开线程来初始化,同时该函数也可以用于重新扫描设备。
蓝牙连接
private async void BoothConnect() { try { if (BoothChoose.Items.Count != 0) { string selectedDeviceName = BoothChoose.SelectedItem.ToString(); // 寻找匹配的设备 BluetoothDeviceInfo deviceToConnect = devices.FirstOrDefault(d => d.DeviceName == selectedDeviceName); if (deviceToConnect != null) { // 连接到设备 await Task.Run(() => client.Connect(deviceToConnect.DeviceAddress, BluetoothService.SerialPort)); MessageBox.Show("连接成功", "信息"); if (client.Connected) { stream = client.GetStream(); StartListening(OnDataReceived); // 开始监听数据并指定回调 } } else { MessageBox.Show("未找到选定的设备", "警告"); } } else { MessageBox.Show("未检测到设备", "警告"); } } catch (Exception ex) { MessageBox.Show("蓝牙连接失败: " + ex.Message, "错误"); } }
连接蓝牙的代码,根据选择控件选择的蓝牙名称匹配对应的蓝牙设别,接着使用异步的方式来连接蓝牙,防止连接蓝牙的过程中导致UI线程卡顿无法使用。
并且使用一个Stream流变量来接收蓝牙传输的信息,调用StartListening函数来实现蓝牙设备的监听
监听函数
private void StartListening(Action<string> callback) { Task.Run(() => { byte[] buffer = new byte[1024]; // 数据缓冲区 int bytes; try { while (client.Connected) { bytes = stream.Read(buffer, 0, buffer.Length); if (bytes > 0) { string receivedData = Encoding.UTF8.GetString(buffer, 0, bytes); this.Invoke((MethodInvoker)delegate { callback(receivedData); // 在UI线程上调用回调 }); } } } catch (IOException ex) { // 连接丢失或读取错误 this.Invoke((MethodInvoker)delegate { MessageBox.Show("读取数据错误: " + ex.Message, "错误"); }); } }); } private void OnDataReceived(string data) { if (Receive.InvokeRequired) { // 如果调用线程不是创建Receive控件的线程,则使用Invoke调用 Receive.Invoke(new MethodInvoker(delegate { Receive.AppendText(data); })); } else { // 如果已经在UI线程,则直接更新 Receive.AppendText(data); } }
监听函数中我们异步监听数据,并且设置OnDataReceived回调函数处理接收到的数据。
发送数据
private void TransButton_Click(object sender, EventArgs e) { try { // 获取要发送的文本 string dataToSend = TransText.Text; if (NewLine.Checked) { dataToSend += Environment.NewLine; } if (client != null && client.Connected) { Stream stream = client.GetStream(); if (stream.CanWrite) { // 将文本转换为字节数据 byte[] buffer = Encoding.UTF8.GetBytes(dataToSend); // 发送数据 stream.Write(buffer, 0, buffer.Length); } } else { MessageBox.Show("Bluetooth is not connected."); } } catch (Exception ex) { MessageBox.Show("Error sending data: " + ex.Message); } }