
自己編寫基于Qt的Android軟件,用于實現(xiàn)手機與TB-02-kit模塊進行數(shù)據(jù)通訊;
Android軟件發(fā)送的數(shù)據(jù),經(jīng)TB-02-kit模塊轉(zhuǎn)發(fā)至串口助手中輸出;
串口助手發(fā)送的數(shù)據(jù)可以在Android軟件中顯示,進而實現(xiàn)BLE的數(shù)據(jù)雙向通信。
給大家介紹一款好用的藍(lán)牙BT5.0透傳模塊
Windows下基于Qt開發(fā)Android應(yīng)用
BLE中這些概念你都了解嗎
因為是第一次分享Qt代碼,為了方便大家學(xué)習(xí),代碼中添加了大量注釋,大家對照著代碼學(xué)習(xí)效率高點。
后臺回復(fù)關(guān)鍵字“Android-BLE”,獲取本文涉及到的軟件及Qt工程源碼。


在構(gòu)造函數(shù)中執(zhí)行藍(lán)牙設(shè)備掃描,即軟件一啟動就執(zhí)行掃描。
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//創(chuàng)建搜索服務(wù):https://doc.qt.io/qt-5/qbluetoothdevicediscoveryagent.html
discoveryAgent =new QBluetoothDeviceDiscoveryAgent(this);
//設(shè)置BLE的搜索時間
discoveryAgent->setLowEnergyDiscoveryTimeout(20000);
connect(discoveryAgent,SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),this,SLOT(addBlueToothDevicesToList(QBluetoothDeviceInfo)));//找到設(shè)備之后添加到列表顯示出來
connect(discoveryAgent, SIGNAL(finished()), this, SLOT(scanFinished()));
connect(discoveryAgent, SIGNAL(canceled()), this, SLOT(scanCanceled()));
connect(this, SIGNAL(returnAddress(QBluetoothDeviceInfo)), this, SLOT(createCtl(QBluetoothDeviceInfo)));
//開始進行設(shè)備搜索
discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
}
//deviceDiscovered signals 對應(yīng)的槽函數(shù)
void Widget::addBlueToothDevicesToList(const QBluetoothDeviceInfo &info)
{
if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) //獲取設(shè)備信息,并判斷該設(shè)備是否為BLE設(shè)備
{
//格式化設(shè)備地址和設(shè)備名稱
QString label = QString("%1 %2").arg(info.address().toString()).arg(info.name());
//檢查設(shè)備是否已存在,避免重復(fù)添加
QList<QListWidgetItem *> items = ui->ctrBleList->findItems(label, Qt::MatchExactly);
//不存在則添加至設(shè)備列表
if (items.empty())
{
QListWidgetItem *item = new QListWidgetItem(label);
ui->ctrBleList->addItem(item);
devicesList.append(info);
}
}
}
void Widget::on_btnConnectBle_clicked()
{
//確認(rèn)選取了某一個藍(lán)牙設(shè)備
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);
//發(fā)送自定義signals==>執(zhí)行slots:createCtl
emit returnAddress(choosenDevice);
//停止搜索服務(wù)
discoveryAgent->stop();
break;
}
}
}
}
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())
{
//返回特征的屬性。
//這些屬性定義了特征的訪問權(quán)限。
if(c.properties() & QLowEnergyCharacteristic::WriteNoResponse || c.properties() & QLowEnergyCharacteristic::Write)
{
ui->ctrSystemLogInfo->insertPlainText("\n具有寫權(quán)限!");
m_writeCharacteristic = c; //保存寫權(quán)限特性
if(c.properties() & QLowEnergyCharacteristic::WriteNoResponse)
{
m_writeMode = QLowEnergyService::WriteWithoutResponse;
}
else
{
m_writeMode = QLowEnergyService::WriteWithResponse;
}
}
if(c.properties() & QLowEnergyCharacteristic::Read)
{
m_readCharacteristic = c; //保存讀權(quán)限特性
}
//描述符定義特征如何由特定客戶端配置。
m_notificationDesc = c.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
//值為真
if(m_notificationDesc.isValid())
{
//寫描述符
m_bleServer->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0100"));
ui->ctrSystemLogInfo->insertPlainText("\n寫描述符!");
}
}
}
}
}
writeCharacteristic()方法,發(fā)送數(shù)據(jù)給ble設(shè)備。
點擊界面中的"發(fā)送"按鈕,發(fā)送"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");
}
通過藍(lán)牙QLowEnergyService::characteristicRead的回調(diào)接口,接收藍(lán)牙收到的消息。
void Widget::BleServiceCharacteristicRead(const QLowEnergyCharacteristic &c,const QByteArray &value)
{
Q_UNUSED(c)
ui->ctrSystemLogInfo->insertPlainText("\n當(dāng)特征讀取請求成功返回其值時:");
ui->ctrSystemLogInfo->insertPlainText(QString(value));
}
Widget::~Widget()
{
if(!(m_BLEController->state() == QLowEnergyController::UnconnectedState))
m_BLEController->disconnectFromDevice();//從設(shè)備斷開鏈接
delete ui;
}
如果出現(xiàn)" Cannot connect to remote device. " ,可以點擊"連接"按鈕重新連接一下。
本實例只是演示一下Android手機與TB-02-kit模塊的通訊過程,程序里有需要完善的地方,比如,應(yīng)該增加一個"掃描"按鈕,而不是軟件啟動過程中直接進行藍(lán)牙掃描,這樣的話,就需要藍(lán)牙的上電要在軟件啟動之前完成。
程序的健壯性也要完善,比如偶爾會出現(xiàn)與模塊無法正常連接的情況,需要再次點擊"連接"按鈕才可,這些工作你們自己可以完善一下哈。
有了本部分知識,下一步我們結(jié)合Android手機和TB-02-kit模塊,實現(xiàn)STM32的設(shè)備的遠(yuǎn)程控制。
Button控件右鍵菜單中選中“轉(zhuǎn)到槽...”,然后在彈出列表中選中信號:“clicked() ”,然后點擊OK按鈕,即可進入其事件函數(shù)中。
Qt官方文檔:https://doc.qt.io/qt-5/classes.html
程序員小哈帶你玩轉(zhuǎn)嵌入式,微信搜索:嵌入式從0到1,更多干貨等著你。
嵌入式交流群1群還剩9個坑位,要進的速速進哈,過一陣開2群。