利用ESP32來模擬BT藍(lán)牙(BLE低功耗藍(lán)牙后續(xù)也會(huì)進(jìn)行測(cè)試)
C#利用32feet.NET庫(kù)來實(shí)現(xiàn)藍(lán)牙的使用。
這個(gè)界面基本也是搬運(yùn)至前面的串口助手界面,目前制作了發(fā)送和接收界面。并且代碼邏輯也比較簡(jiǎn)單,還需要有很大的修改。(1)初始化掃描藍(lán)牙設(shè)備寫入選擇框(2)連接藍(lán)牙設(shè)備,連接成功則開啟監(jiān)聽線程(3)監(jiān)聽線程接收到數(shù)據(jù)設(shè)置回調(diào)函數(shù)將接收到的內(nèi)容顯示在文本框上。(4)點(diǎn)擊發(fā)送按鈕后將文本框的內(nèi)容發(fā)送給接收端。
private async void Booth_Init()
{
try
{
client = new BluetoothClient();
// 使用 Task.Run 來在另一個(gè)線程中執(zhí)行 DiscoverDevices
devices = await Task.Run(() => client.DiscoverDevices());
BoothChoose.Items.Clear();
foreach (BluetoothDeviceInfo device in devices)
{
// 確保 UI 更新在 UI 線程上執(zhí)行
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("錯(cuò)誤: " + ex.Message);
}
}
初始化的代碼是使用異步的方式掃描設(shè)備,并且將設(shè)備名稱顯示在選擇控件上,之所以是采用異步的方式原因是不采用異步會(huì)占用UI線程導(dǎo)致UI線程無法使用。所以需要單獨(dú)開線程來初始化,同時(shí)該函數(shù)也可以用于重新掃描設(shè)備。private async void BoothConnect()
{
try
{
if (BoothChoose.Items.Count != 0)
{
string selectedDeviceName = BoothChoose.SelectedItem.ToString();
// 尋找匹配的設(shè)備
BluetoothDeviceInfo deviceToConnect = devices.FirstOrDefault(d => d.DeviceName == selectedDeviceName);
if (deviceToConnect != null)
{
// 連接到設(shè)備
await Task.Run(() => client.Connect(deviceToConnect.DeviceAddress, BluetoothService.SerialPort));
MessageBox.Show("連接成功", "信息");
if (client.Connected)
{
stream = client.GetStream();
StartListening(OnDataReceived); // 開始監(jiān)聽數(shù)據(jù)并指定回調(diào)
}
}
else
{
MessageBox.Show("未找到選定的設(shè)備", "警告");
}
}
else
{
MessageBox.Show("未檢測(cè)到設(shè)備", "警告");
}
}
catch (Exception ex)
{
MessageBox.Show("藍(lán)牙連接失敗: " + ex.Message, "錯(cuò)誤");
}
}
連接藍(lán)牙的代碼,根據(jù)選擇控件選擇的藍(lán)牙名稱匹配對(duì)應(yīng)的藍(lán)牙設(shè)別,接著使用異步的方式來連接藍(lán)牙,防止連接藍(lán)牙的過程中導(dǎo)致UI線程卡頓無法使用。并且使用一個(gè)Stream流變量來接收藍(lán)牙傳輸?shù)男畔?,調(diào)用StartListening函數(shù)來實(shí)現(xiàn)藍(lán)牙設(shè)備的監(jiān)聽private void StartListening(Action<string> callback)
{
Task.Run(() =>
{
byte[] buffer = new byte[1024]; // 數(shù)據(jù)緩沖區(qū)
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線程上調(diào)用回調(diào)
});
}
}
}
catch (IOException ex)
{
// 連接丟失或讀取錯(cuò)誤
this.Invoke((MethodInvoker)delegate
{
MessageBox.Show("讀取數(shù)據(jù)錯(cuò)誤: " + ex.Message, "錯(cuò)誤");
});
}
});
}
private void OnDataReceived(string data)
{
if (Receive.InvokeRequired)
{
// 如果調(diào)用線程不是創(chuàng)建Receive控件的線程,則使用Invoke調(diào)用
Receive.Invoke(new MethodInvoker(delegate
{
Receive.AppendText(data);
}));
}
else
{
// 如果已經(jīng)在UI線程,則直接更新
Receive.AppendText(data);
}
}
監(jiān)聽函數(shù)中我們異步監(jiān)聽數(shù)據(jù),并且設(shè)置OnDataReceived回調(diào)函數(shù)處理接收到的數(shù)據(jù)。
private void TransButton_Click(object sender, EventArgs e)
{
try
{
// 獲取要發(fā)送的文本
string dataToSend = TransText.Text;
if (NewLine.Checked)
{
dataToSend += Environment.NewLine;
}
if (client != null && client.Connected)
{
Stream stream = client.GetStream();
if (stream.CanWrite)
{
// 將文本轉(zhuǎn)換為字節(jié)數(shù)據(jù)
byte[] buffer = Encoding.UTF8.GetBytes(dataToSend);
// 發(fā)送數(shù)據(jù)
stream.Write(buffer, 0, buffer.Length);
}
}
else
{
MessageBox.Show("Bluetooth is not connected.");
}
}
catch (Exception ex)
{
MessageBox.Show("Error sending data: " + ex.Message);
}
}
ESP32中的代碼是利用藍(lán)牙傳輸接收到的信息。
因此我們發(fā)送信息會(huì)接收到發(fā)送的信息。
該文章在 2024/1/31 15:49:23 編輯過