Qt開發(fā)上位機軟件建立經(jīng)典藍牙通訊
之前做了一個具有經(jīng)典藍牙通訊功能的Windows上位機軟件,在網(wǎng)上學習了相關(guān)博客以及參考了官方經(jīng)典藍牙例程之后,總結(jié)出了使用Qt建立經(jīng)典藍牙通訊的步驟,附帶相關(guān)源碼,作為分享
開發(fā)環(huán)境
我使用的Qt
版本是5.15,使用的CMake
構(gòu)建項目。
整體開發(fā)使用的IDE
是Qt Creator
,采用的方式是基于widgets
的ui
設計界面、C++寫邏輯的方式。
編譯使用的是Desktop Qt 5.15.2 MINGW 64-bit
CMake配置
經(jīng)典藍牙通訊需要用到Qt
的藍牙模塊,需要添加Bluetooth
模塊:
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Widgets Bluetooth) #尋找Bluetooth模塊
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets Bluetooth) #尋找Bluetooth模塊
在add_executable
之后設置target_link_libraries
:
target_link_libraries(bluetooth_serial_host_computer PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Bluetooth #添加藍牙
)
包含頭文件
#include <QtBluetooth/QBluetoothLocalDevice> //本地設備
#include <QtBluetooth/QBluetoothDeviceDiscoveryAgent> //設備發(fā)現(xiàn)
#include <QtBluetooth/QBluetoothSocket> //藍牙套接字
#include <QtBluetooth/QBluetoothUuid> //藍牙uuid
#include <QtBluetooth/QBluetoothServiceDiscoveryAgent> //服務發(fā)現(xiàn)
#include <QtBluetooth/QBluetoothServiceInfo> //服務信息
建立經(jīng)典藍牙通訊
建立經(jīng)典藍牙通訊的基本步驟如下:
首先是在構(gòu)造函數(shù)中的初始化操作:
//創(chuàng)建設備發(fā)現(xiàn)對象
m_deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
m_btLocalDevice = new QBluetoothLocalDevice(); //創(chuàng)建本地設備對象
m_btSocket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); //藍牙套接字
QBluetoothAddress adapterAddress = m_btLocalDevice->address(); //使用默認藍牙適配器
m_serviceDiscoveryAgent = new QBluetoothServiceDiscoveryAgent(adapterAddress); //創(chuàng)建服務發(fā)現(xiàn)對象
//連接信號與槽(deviceDiscoveryAgent是代碼中自己聲明的對象,ui中沒有,無法自動生成槽函數(shù);需要自己寫槽函數(shù),自己連接)
/*-------------------- 初始化設備列表與服務列表 -----------------*/
//設置設備列表
QListWidgetItem* item = new QListWidgetItem();
//創(chuàng)建自定義窗口,放入到listwidget中
BluetoothDeviceCell* btDevCell = new BluetoothDeviceCell();
//設置item的高
item->setSizeHint(QSize(ui->deviceListWidget->width(), btDevCell->height()));
//設置label顯示
//第一個加進去的item在最上面,相當于標題
btDevCell->m_btName->setText("名稱");
btDevCell->m_btAddr->setText("地址");
btDevCell->m_btRssi->setText("信號強度");
//將item加入到listwidget中
ui->deviceListWidget->addItem(item);
//設置item的窗口為自定義的窗口
ui->deviceListWidget->setItemWidget(item, btDevCell);
//設置服務列表的標題
QListWidgetItem* items = new QListWidgetItem();
//創(chuàng)建自定義窗口,放入到listwidget中
BluetoothDeviceCell* btDevCells = new BluetoothDeviceCell();
//設定item的尺寸
items->setSizeHint(QSize(ui->serviceListWidget->width(), btDevCells->height()));
//設置label的顯示
//第一個加進去的item在最上面,相當于標題
btDevCells->m_btName->setText("名稱");
btDevCells->m_btAddr->setText("服務Uuid");
btDevCells->m_btRssi->setText("空");
//將item加入到listwidget中
ui->serviceListWidget->addItem(items);
//設置item的窗口為自定義的窗口
ui->serviceListWidget->setItemWidget(items, btDevCells);
/*------------- m_deviceDiscoveryAgent設備搜索對象的信號槽 -------------*/
connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BluetoothConnect::deviceDiscoveredSlot);//發(fā)現(xiàn)設備
connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &BluetoothConnect::deviceSearchFinishedSlot);//搜索完畢
void (QBluetoothDeviceDiscoveryAgent:: *deviceSearchErrorOccurred)(QBluetoothDeviceDiscoveryAgent::Error) = &QBluetoothDeviceDiscoveryAgent::error;//有重載
connect(m_deviceDiscoveryAgent, deviceSearchErrorOccurred, this, &BluetoothConnect::deviceSearchErrorOccurredSlot);//設備搜索發(fā)生錯誤
/*------------- m_btSocket藍牙套接字的信號槽 ----------------*/
void (QBluetoothSocket:: *socketErrorOccurred)(QBluetoothSocket::SocketError) = &QBluetoothSocket::error;
connect(m_btSocket, socketErrorOccurred, this, &BluetoothConnect::socketErrorOccurredSlot); //錯誤處理槽函數(shù)
connect(m_btSocket, &QBluetoothSocket::connected, this, &BluetoothConnect::socketConnectedSlot);//連接成功
/*------------- m_serviceDiscoveryAgent服務發(fā)現(xiàn)對象的信號槽 ---------------*/
connect(m_serviceDiscoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, this, &BluetoothConnect::serviceDiscoveredSlot); //發(fā)現(xiàn)一個服務
connect(m_serviceDiscoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, this, &BluetoothConnect::serviceSearchFinishedSlot); //服務搜索完畢
deviceListWidget和serviceListWidget是我在ui中設置的兩個列表組件,用來存放設備和服務信息。
搜索設備
利用QBluetoothDeviceDiscoveryAgent
的start
方法即可開啟設備搜索:
void BluetoothConnect::on_searchButton_clicked() //點擊Search按鈕后開始搜索設備
{
//如果已經(jīng)搜索過1次,那么設備列表可能會大于1,需要先清空設備列表
//但是標題也會被清除,所以重新添加標題
if(ui->deviceListWidget->count() > 1)
{
ui->deviceListWidget->clear();
//設置設備列表
QListWidgetItem* item = new QListWidgetItem();
//創(chuàng)建自定義窗口,放入到listwidget中
BluetoothDeviceCell* btDevCell = new BluetoothDeviceCell();
//設置item的高
item->setSizeHint(QSize(ui->deviceListWidget->width(), btDevCell->height()));
//設置label顯示
btDevCell->m_btName->setText("名稱");
btDevCell->m_btAddr->setText("地址");
btDevCell->m_btRssi->setText("信號強度");
//將item加入到listwidget中
ui->deviceListWidget->addItem(item);
//設置item的窗口為自定義的窗口
ui->deviceListWidget->setItemWidget(item, btDevCell);
}
m_deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::ClassicMethod); //開啟經(jīng)典藍牙設備搜索
ui->searchButton->setEnabled(false);//搜索過程中,search按鈕不可點擊
ui->statusLabel->setText("Searching for devices......");
}
QBluetoothDeviceDiscoveryAgent::ClassicMethod
是以經(jīng)典方式進行搜索,可以發(fā)現(xiàn)經(jīng)典藍牙和低功耗藍牙設備。
發(fā)現(xiàn)一個設備的槽函數(shù):
void BluetoothConnect::deviceDiscoveredSlot(QBluetoothDeviceInfo btDevInfo) //發(fā)現(xiàn)設備后將設備添加到listwidget中
{
QListWidgetItem* item = new QListWidgetItem(); //聲明一個item
BluetoothDeviceCell* btDevCell = new BluetoothDeviceCell(); //聲明一個藍牙設備單元
item->setSizeHint(QSize(ui->deviceListWidget->width(), btDevCell->height())); //設定item的尺寸
//搜索到的設備信息存到設備單元中
btDevCell->m_btName->setText(btDevInfo.name());
btDevCell->m_btAddr->setText(btDevInfo.address().toString());
btDevCell->m_btRssi->setText(QString::number(btDevInfo.rssi()));
//將設備單元添加到deviceListWidget中
ui->deviceListWidget->addItem(item);
ui->deviceListWidget->setItemWidget(item,btDevCell);
//設備信息list新增一個設備信息
m_devInfos.append(btDevInfo);
}
設備搜索完成的槽函數(shù):
void BluetoothConnect::deviceSearchFinishedSlot() //設備搜索完成
{
ui->statusLabel->setText("Double Click a device to searhc for services");
QMessageBox::about(this, "提示", "設備搜索完成");
// qDebug() << "搜索已完成";
ui->searchButton->setEnabled(true); //一次搜索完之后才可以重新點擊search鍵
}
設備搜索出現(xiàn)錯誤的槽函數(shù):
void BluetoothConnect::deviceSearchErrorOccurredSlot(QBluetoothDeviceDiscoveryAgent::Error error) //搜索藍牙設備出現(xiàn)錯誤
{
qDebug() << error;
//警告對話框
QMessageBox::warning(this, "警告!", "搜索藍牙設備發(fā)生錯誤,請檢查藍牙是否開啟");
}
搜索選定設備的服務
激活設備列表的設備,搜索這個選定設備的服務:
void BluetoothConnect::on_deviceListWidget_itemActivated(QListWidgetItem *item) //點擊設備列表中的item
{
/***
* 點擊設備后,搜索設備的服務。點擊服務后,根據(jù)服務和設備進行連接。并將socket的準備接收與主窗口BluetoothDebugger的revDataTextEdit的顯示連接
*/
//在開始service搜索之前先重置服務列表
//如果已經(jīng)搜索過1次,那么服務列表可能會大于1,需要先清空服務列表
//但是標題也會被清除,所以重新添加標題
if(ui->serviceListWidget->count() > 1)
{
ui->serviceListWidget->clear();
//設置服務列表的標題
QListWidgetItem* items = new QListWidgetItem();
//創(chuàng)建自定義窗口,放入到listwidget中
BluetoothDeviceCell* btDevCells = new BluetoothDeviceCell();
//設定item的尺寸
items->setSizeHint(QSize(ui->serviceListWidget->width(), btDevCells->height()));
//設置label的顯示
//第一個加進去的item在最上面,相當于標題
btDevCells->m_btName->setText("名稱");
btDevCells->m_btAddr->setText("服務Uuid");
btDevCells->m_btRssi->setText("空");
//將item加入到listwidget中
ui->serviceListWidget->addItem(items);
//設置item的窗口為自定義的窗口
ui->serviceListWidget->setItemWidget(items, btDevCells);
}
QWidget* widget = ui->deviceListWidget->itemWidget(item); //將點擊的item信息取出來
BluetoothDeviceCell* btDevCell = (BluetoothDeviceCell*) widget; //強制類型轉(zhuǎn)換為DeviceCell設備單元
qDebug() << btDevCell->m_btAddr->text(); //輸出設備地址
m_btAddress = QBluetoothAddress(btDevCell->m_btAddr->text());//記錄下來選中的設備的地址.后邊點擊service進行連接時,使用該地址
m_serviceDiscoveryAgent->setRemoteAddress(QBluetoothAddress(btDevCell->m_btAddr->text())); //要搜索的服務是當前激活的這個設備的服務
m_serviceDiscoveryAgent->start(); //開始搜索
ui->statusLabel->setText("Searching for services......");
//!!!!不同設備所允許的服務不同,需要尋找設備支持的服務有什么
}
發(fā)現(xiàn)一個服務的槽函數(shù),將服務信息添加到listWidget
以及自己的list
中:
void BluetoothConnect::serviceDiscoveredSlot(const QBluetoothServiceInfo& serviceInfo) //發(fā)現(xiàn)服務
{
//serviceInfo中沒有設備地址
if(serviceInfo.serviceName().isEmpty())
return;
//!!!用serviceClassUuids才能得到有效的Uuid
QList<QBluetoothUuid> btUuids = serviceInfo.serviceClassUuids();
//每個list中只有1個元素
qDebug() << btUuids[0];
QBluetoothUuid btUuid = btUuids[0];
QListWidgetItem* item = new QListWidgetItem();
BluetoothDeviceCell* btDevCell = new BluetoothDeviceCell();
item->setSizeHint(QSize(ui->serviceListWidget->width(), btDevCell->height()));
btDevCell->m_btName->setText(serviceInfo.serviceName());
btDevCell->m_btAddr->setText(btUuid.toString());
btDevCell->m_btRssi->setText("");
ui->serviceListWidget->addItem(item);
ui->serviceListWidget->setItemWidget(item, btDevCell);
m_btUuids.append(btUuid);
}
服務搜索完成的槽函數(shù):
void BluetoothConnect::serviceSearchFinishedSlot() //服務搜索完成
{
ui->statusLabel->setText("Double Click a service to connect to bluetooth");
QMessageBox::about(this, "Hint", "Service Search Finished!");
}
連接到選定設備的選定服務,建立通訊
激活服務列表的服務的槽函數(shù):
void BluetoothConnect::on_serviceListWidget_itemActivated(QListWidgetItem *item) //激活服務列表的項目
{
QWidget* widget = ui->serviceListWidget->itemWidget(item); //將點擊的item信息取出來
BluetoothDeviceCell* btDevCell = (BluetoothDeviceCell*) widget; //強制類型轉(zhuǎn)換為DeviceCell設備單元
qDebug() << m_btAddress << btDevCell->m_btAddr->text();
m_btSocket->connectToService(m_btAddress,QBluetoothUuid(btDevCell->m_btAddr->text()),QIODevice::ReadWrite); //根據(jù)設備地址與Uuid連接
ui->statusLabel->setText("Bluetooth connecting......");
}
使用socket
套接字連接成功后,經(jīng)典藍牙通訊即建立:
void BluetoothConnect::socketConnectedSlot() //socket連接成功
{
ui->statusLabel->setText("");
QMessageBox::about(this, "Information", "Socket Connected Successfully!");
//隱去Bluetooth Connect窗口
this->close();
}
socket
發(fā)生錯誤的槽函數(shù):
void BluetoothConnect::socketErrorOccurredSlot(QBluetoothSocket::SocketError error) //socket發(fā)生錯誤
{
switch(error)
{
case QBluetoothSocket::NoSocketError:
break;
case QBluetoothSocket::UnknownSocketError:
qDebug() << "Error: Unknown Socket Error!";
break;
case QBluetoothSocket::RemoteHostClosedError:
qDebug() << "Error: Remote Host Closed Error!";
break;
case QBluetoothSocket::HostNotFoundError:
qDebug() << "Error: Host Not Found Error!";
break;
case QBluetoothSocket::ServiceNotFoundError:
qDebug() << "Error: Service Not Found Error!";
break;
case QBluetoothSocket::NetworkError:
qDebug() << "Error: Network Error!";
break;
case QBluetoothSocket::UnsupportedProtocolError:
qDebug() << "Error: Unsupported Protocol Error!";
break;
case QBluetoothSocket::OperationError:
qDebug() << "Error: Operation Error!";
break;
}
}
接收數(shù)據(jù)使用socket
,將readyRead
的signal
與槽函數(shù)連接:
void BluetoothDebugger::socketReadyReadSlot() //socket準備好讀取
{
char data[100];
qint64 len = m_btConnect->m_btSocket->read((char*)data,100);
QByteArray byteArray((char*)data, len);
if(m_isClose == false) //窗口顯示打開
{
ui->revDataTextBrowser->append("接收:");
ui->revDataTextBrowser->append(byteArray);//添加到窗口
}
}
發(fā)送數(shù)據(jù)也是使用socket
套接字:文章來源:http://www.zghlxwxcb.cn/news/detail-416290.html
void BluetoothDebugger::on_sendButton_clicked() //點擊發(fā)送按鈕
{
//被發(fā)送的數(shù)據(jù)
QByteArray dataSent = ui->sendDataLineEdit->text().toUtf8();
if(m_isClose == false) //窗口顯示打開,藍牙發(fā)送使能;窗口顯示關(guān)閉,藍牙發(fā)送失能
{
//將發(fā)送的數(shù)據(jù)也打印到窗口上
ui->revDataTextBrowser->append("發(fā)送:");
ui->revDataTextBrowser->append(dataSent);
//通過socket發(fā)送數(shù)據(jù)
m_btConnect->m_btSocket->write(dataSent);
}
}
以上即為使用Qt建立經(jīng)典藍牙通訊的基本步驟。文章來源地址http://www.zghlxwxcb.cn/news/detail-416290.html
到了這里,關(guān)于Qt開發(fā)上位機軟件建立經(jīng)典藍牙通訊的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!