Qt編程實例:基于Android的BLE通信軟件
實現目標
- 自己編寫基于Qt的Android軟件,用于實現手機與TB-02-kit模塊進行數據通訊;
- Android軟件發送的數據,經TB-02-kit模塊轉發至串口助手中輸出;
- 串口助手發送的數據可以在Android軟件中顯示,進而實現BLE的數據雙向通信。
所需工具及環境
- TB-02-kit模塊
- Qt Creator 4.10.1
- Qt 5.13.1
- XCOM V2.0 串口助手
- Android 手機
- 本人電腦 Windows 10 64bit [版本 10.0.19041.329]
本文源碼
因為是第一次分享Qt代碼,為了方便大家學習,代碼中添加了大量注釋,大家對照著代碼學習效率高點。
后臺回復關鍵字“Android-BLE”,獲取本文涉及到的軟件及Qt工程源碼。
具體實現
1. 要使用Qt藍牙模塊, 項目的 .pro文件中要添加聲明才可使用
2. 掃描設備
在構造函數中執行藍牙設備掃描,即軟件一啟動就執行掃描。
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::Widget)
- {
- ui->setupUi(this);
- //創建搜索服務:https://doc.qt.io/qt-5/qbluetoothdevicediscoveryagent.html
- discoveryAgent =new QBluetoothDeviceDiscoveryAgent(this);
- //設置BLE的搜索時間
- discoveryAgent->setLowEnergyDiscoveryTimeout(20000);
- connect(discoveryAgent,SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),this,SLOT(addBlueToothDevicesToList(QBluetoothDeviceInfo)));//找到設備之后添加到列表顯示出來
- connect(discoveryAgent, SIGNAL(finished()), this, SLOT(scanFinished()));
- connect(discoveryAgent, SIGNAL(canceled()), this, SLOT(scanCanceled()));
- connect(this, SIGNAL(returnAddress(QBluetoothDeviceInfo)), this, SLOT(createCtl(QBluetoothDeviceInfo)));
- //開始進行設備搜索
- discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
- }
3. 將掃描結果添加到QListWidget中
- //deviceDiscovered signals 對應的槽函數
- void Widget::addBlueToothDevicesToList(const QBluetoothDeviceInfo &info)
- {
- if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) //獲取設備信息,并判斷該設備是否為BLE設備
- {
- //格式化設備地址和設備名稱
- QString label = QString("%1 %2").arg(info.address().toString()).arg(info.name());
- //檢查設備是否已存在,避免重復添加
- QList<QListWidgetItem *> items = ui->ctrBleList->findItems(label, Qt::MatchExactly);
- //不存在則添加至設備列表
- if (items.empty())
- {
- QListWidgetItem *item = new QListWidgetItem(label);
- ui->ctrBleList->addItem(item);
- devicesList.append(info);
- }
- }
- }
4. 連接藍牙,停止掃描
- void Widget::on_btnConnectBle_clicked()
- {
- //確認選取了某一個藍牙設備
- if(!ui->ctrBleList->currentItem()->text().isEmpty())
- {
- //獲取選擇的地址
- QString bltAddress = ui->ctrBleList->currentItem()->text().left(17);
- for (int i = 0; i<devicesList.count(); i++)
- {
- //地址對比
- if(devicesList.at(i).address().toString().left(17) == bltAddress)
- {
- QBluetoothDeviceInfo choosenDevice = devicesList.at(i);
- //發送自定義signals==>執行slots:createCtl
- emit returnAddress(choosenDevice);
- //停止搜索服務
- discoveryAgent->stop();
- break;
- }
- }
- }
- }
5. 獲取特征
- void Widget::searchCharacteristic()
- {
- if(m_bleServer)
- {
- QList<QLowEnergyCharacteristic> list=m_bleServer->characteristics();
- qDebug()<<"[xiaohage]list.count()="<<list.count();
- //遍歷characteristics
- for(int i=0;i<list.count();i++)
- {
- QLowEnergyCharacteristic c=list.at(i);
- /*如果QLowEnergyCharacteristic對象有效,則返回true,否則返回false*/
- if(c.isValid())
- {
- //返回特征的屬性。
- //這些屬性定義了特征的訪問權限。
- if(c.properties() & QLowEnergyCharacteristic::WriteNoResponse || c.properties() & QLowEnergyCharacteristic::Write)
- {
- ui->ctrSystemLogInfo->insertPlainText("\n具有寫權限!");
- m_writeCharacteristic = c; //保存寫權限特性
- if(c.properties() & QLowEnergyCharacteristic::WriteNoResponse)
- {
- m_writeMode = QLowEnergyService::WriteWithoutResponse;
- }
- else
- {
- m_writeMode = QLowEnergyService::WriteWithResponse;
- }
- }
- if(c.properties() & QLowEnergyCharacteristic::Read)
- {
- m_readCharacteristic = c; //保存讀權限特性
- }
- //描述符定義特征如何由特定客戶端配置。
- m_notificationDesc = c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
- //值為真
- if(m_notificationDesc.isValid())
- {
- //寫描述符
- m_bleServer->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0100"));
- ui->ctrSystemLogInfo->insertPlainText("\n寫描述符!");
- }
- }
- }
- }
- }
6. 發送數據
writeCharacteristic()方法,發送數據給ble設備。
點擊界面中的"發送"按鈕,發送"Hello World"字符串。
- void Widget::SendMsg(QString text)
- {
- QByteArray array=text.toLocal8Bit();
- m_bleServer->writeCharacteristic(m_writeCharacteristic,array, m_writeMode);
- }
- void Widget::on_btnSendData_clicked()
- {
- SendMsg("Hello World");
- }
7. 寫入數據
通過藍牙QLowEnergyService::characteristicRead的回調接口,接收藍牙收到的消息。
- void Widget::BleServiceCharacteristicRead(const QLowEnergyCharacteristic &c,const QByteArray &value)
- {
- Q_UNUSED(c)
- ui->ctrSystemLogInfo->insertPlainText("\n當特征讀取請求成功返回其值時:");
- ui->ctrSystemLogInfo->insertPlainText(QString(value));
- }
8. 斷開連接
- Widget::~Widget()
- {
- if(!(m_BLEController->state() == QLowEnergyController::UnconnectedState))
- m_BLEController->disconnectFromDevice();//從設備斷開鏈接
- delete ui;
- }
界面布局
結果展示
如果出現" Cannot connect to remote device. " ,可以點擊"連接"按鈕重新連接一下。
串口助手及應用程序輸出
To do
本實例只是演示一下Android手機與TB-02-kit模塊的通訊過程,程序里有需要完善的地方,比如,應該增加一個"掃描"按鈕,而不是軟件啟動過程中直接進行藍牙掃描,這樣的話,就需要藍牙的上電要在軟件啟動之前完成。
程序的健壯性也要完善,比如偶爾會出現與模塊無法正常連接的情況,需要再次點擊"連接"按鈕才可,這些工作你們自己可以完善一下哈。
有了本部分知識,下一步我們結合Android手機和TB-02-kit模塊,實現STM32的設備的遠程控制。
Qt小知識
1. Qt Creator程序輸出窗口過濾調試信息
2. 為Button添加事件
Button控件右鍵菜單中選中“轉到槽...”,然后在彈出列表中選中信號:“clicked() ”,然后點擊OK按鈕,即可進入其事件函數中。
參考資料
Qt官方文檔:https://doc.qt.io/qt-5/classes.html
本文轉載自微信公眾號「嵌入式從0到1」,可以通過以下二維碼關注。轉載本文請聯系嵌入式從0到1公眾號。