时间记录:2024/1/22
一、注意点
(1)pro文件中引入bluetooth模块
(2)安卓端运行时需要同步打开定位功能才能扫描到蓝牙设备
(3)mingw套件不能在Windows上运行,需要使用MSVC套件编译才能在Windows上运行
二、使用步骤
(1)设备蓝牙操作类QBluetoothLocalDevice
2.1.1 hostMode方法获取蓝牙打开状态
2.1.2 powerOn方法打开蓝牙
2.1.3 setHostMode方法关闭蓝牙
(2)蓝牙设备搜索类QBluetoothDeviceDiscoveryAgent
2.2.1 setLowEnergyDiscoveryTimeout方法设置扫描超时时间,如果设置为0,则一直进行扫描
2.2.2 为QBluetoothDeviceDiscoveryAgent对象的deviceDiscovered信号绑定槽,每发现一台蓝牙设备便会触发一次此信号,携带参数QBluetoothDeviceInfo,每台蓝牙设备的信息类
2.2.3 使用start方法,开始搜索蓝牙设备,参数可以传递QBluetoothDeviceDiscoveryAgent::LowEnergyMethod表示搜索低功耗蓝牙设备
(3)低功耗蓝牙控制器类QLowEnergyController
2.3.1 使用静态方法createCentral创建蓝牙控制器对象,参数为QBluetoothDeviceInfo对象
2.3.2 为serviceDiscovered信号绑定槽,每发现一个服务触发一次此信号,携带参数QBluetoothUuid
2.3.3 为connected信号绑定槽,用于判断是否已成功连接到蓝牙
2.3.4 使用connectToDevice方法连接蓝牙
2.3.5 使用disconnectFromDevice方法来断开连接
2.3.6 连接成功后调用discoverServices方法获取连接蓝牙下的所有服务
(4)低功耗蓝牙服务类QLowEnergyService
2.4.1 使用QLowEnergyController对象的createServiceObject方法创建QLowEnergyService对象
2.4.2 为stateChanged信号绑定槽,监听服务状态
2.4.3 为characteristicChanged信号绑定槽,收到信息时会触发此信号,信息为携带的参数newValue
2.4.4 为descriptorWritten信号绑定槽,监听描述符是否成功写入
2.4.5 使用discoverDetails方法获取服务详情
2.4.6 服务状态改变以后写入描述符激活notify,否则无法收到消息,使用characteristics方法获取服务下所有的特征对象
(5)低功耗蓝牙特征值类QLowEnergyCharacteristic
2.5.1 遍历特征值对象列表,使用isValid方法判断是否可用
2.5.2 使用descriptor方法创建描述符对象,参数传递QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration,表示描述符类型由客户端特征值自行配置
(6)低功耗蓝牙描述符对象QLowEnergyDescriptor
2.6.1 使用isValid方法判断描述符对象是否有效
2.6.2 使用QLowEnergyService类的writeDescriptor方法向蓝牙写入描述符,激活notify,参数第一个为描述符对象,第二个为QByteArray::fromHex(“0100”)
(7)使用QLowEnergyService类的writeCharacteristic方法写入数据
三、参考代码
(1)头文件
#ifndef MWIDGET_H
#define MWIDGET_H#include <QWidget>
#include <QBluetoothDeviceDiscoveryAgent> //蓝牙设备搜索对象
#include <QBluetoothLocalDevice> //本机蓝牙操作
#include <QBluetoothDeviceInfo>
#include <QList>
#include <QListWidgetItem>
#include <QLowEnergyController> //蓝牙控制器对象
#include <QBluetoothUuid>
#include <QLowEnergyService>
#include <QLowEnergyCharacteristic>
#include <QByteArray>//static const QLatin1String serviceUUID("0000FFF0-0000-1000-8000-00805F9B34FB");
//static const QLatin1String readUUID("0000FFF1-0000-1000-8000-00805F9B34FB");
//static const QLatin1String writeUUID("0000FFF2-0000-1000-8000-00805F9B34FB");QT_BEGIN_NAMESPACE
namespace Ui { class MWidget; }
QT_END_NAMESPACEclass MWidget : public QWidget
{Q_OBJECTpublic:MWidget(QWidget *parent = nullptr);~MWidget();private:Ui::MWidget *ui;QBluetoothDeviceDiscoveryAgent *deviceDiscoveryAgent;QBluetoothLocalDevice *localDevice;QList<QBluetoothDeviceInfo> *deviceInfoList;QList<QBluetoothUuid> uuidList;QLowEnergyController *control;QLowEnergyService *mService;QLowEnergyCharacteristic mCharacter;QList<QLowEnergyCharacteristic> charList;private slots:void mDeviceDiscovered(QBluetoothDeviceInfo deviceInfo);void on_openLocalDeviceBtn_clicked();void on_closeLocalDeviceBtn_clicked();void on_searchBtn_clicked();void on_listWidget_itemDoubleClicked(QListWidgetItem *item);void mServiceDiscovered(QBluetoothUuid serviceUuid);void mConnected();void on_uuidListWidget_itemDoubleClicked(QListWidgetItem *item);void mStateChanged(QLowEnergyService::ServiceState newState);void mCharacteristicChanged(QLowEnergyCharacteristic characteristic,QByteArray newValue);void mDescriptorWritten(QLowEnergyDescriptor descriptor,QByteArray newValue);void on_pushButton_clicked();
};
#endif // MWIDGET_H
(2)源文件
#include "mwidget.h"
#include "ui_mwidget.h"
#include <QTextCodec>MWidget::MWidget(QWidget *parent): QWidget(parent), ui(new Ui::MWidget)
{ui->setupUi(this);this->setLayout(ui->verticalLayout_2);//创建对象deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);localDevice = new QBluetoothLocalDevice(this);deviceInfoList = new QList<QBluetoothDeviceInfo>();deviceDiscoveryAgent->setLowEnergyDiscoveryTimeout(5000);//连接槽connect(deviceDiscoveryAgent,SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),this,SLOT(mDeviceDiscovered(QBluetoothDeviceInfo)));
}MWidget::~MWidget()
{delete ui;
}//蓝牙设备发现槽
void MWidget::mDeviceDiscovered(QBluetoothDeviceInfo deviceInfo)
{//如果名称不为空切为低功耗蓝牙if(deviceInfo.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration){QString label = QString("%1 %2").arg(deviceInfo.name()).arg(deviceInfo.address().toString());ui->listWidget->addItem(label);deviceInfoList->append(deviceInfo);}
}//打开本地蓝牙
void MWidget::on_openLocalDeviceBtn_clicked()
{if(localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff){localDevice->powerOn();}
}//关闭本地蓝牙
void MWidget::on_closeLocalDeviceBtn_clicked()
{localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
}void MWidget::on_searchBtn_clicked()
{ui->listWidget->clear();deviceInfoList->clear();deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
}//双击连接设备
void MWidget::on_listWidget_itemDoubleClicked(QListWidgetItem *item)
{deviceDiscoveryAgent->stop();Q_UNUSED(item);uuidList.clear();//创建蓝牙控制器对象control = QLowEnergyController::createCentral(deviceInfoList->at(ui->listWidget->currentRow()));connect(control,SIGNAL(serviceDiscovered(QBluetoothUuid)),this,SLOT(mServiceDiscovered(QBluetoothUuid)));connect(control,SIGNAL(connected()),this,SLOT(mConnected()));control->connectToDevice();
}//发现服务uuid
void MWidget::mServiceDiscovered(QBluetoothUuid serviceUuid)
{QString label = QString("%1").arg(serviceUuid.toString());ui->uuidListWidget->addItem(label);uuidList.append(serviceUuid);
}//成功连接到设备
void MWidget::mConnected()
{ui->textBrowser->append("成功连接"+deviceInfoList->at(ui->listWidget->currentRow()).name());//搜索服务uuidList.clear();control->discoverServices();
}//双击创建服务UUID,写描述符,建立通讯
void MWidget::on_uuidListWidget_itemDoubleClicked(QListWidgetItem *item)
{Q_UNUSED(item);//创建服务mService = control->createServiceObject(uuidList.at(ui->uuidListWidget->currentRow()),this);if(mService == NULL){ui->textBrowser->append("创建服务失败");}else{ui->textBrowser->append("服务创建成功");ui->comboBox->clear();//监听服务状态变化connect(mService,SIGNAL(stateChanged(QLowEnergyService::ServiceState)),this,SLOT(mStateChanged(QLowEnergyService::ServiceState)));//服务的characteristic变化,有数据传来connect(mService,SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)),this,SLOT(mCharacteristicChanged(QLowEnergyCharacteristic,QByteArray)));//描述符成功被写connect(mService,SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray)),this,SLOT(mDescriptorWritten(QLowEnergyDescriptor,QByteArray)));//服务详情发现函数mService->discoverDetails();}
}//服务状态改变
void MWidget::mStateChanged(QLowEnergyService::ServiceState newState)
{Q_UNUSED(newState);//发现服务if(mService->state() == QLowEnergyService::ServiceDiscovered){charList = mService->characteristics();for(int i=0;i<charList.size();i++){mCharacter = charList.at(i);if(mCharacter.isValid()){ui->comboBox->addItem(mCharacter.uuid().toString());QLowEnergyDescriptor descriptor = mCharacter.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);if(descriptor.isValid()){mService->writeDescriptor(descriptor,QByteArray::fromHex("0100"));}}}}
}//characteristic变化,数据传来
void MWidget::mCharacteristicChanged(QLowEnergyCharacteristic characteristic, QByteArray newValue)
{ui->textBrowser->append("接收值成功");Q_UNUSED(characteristic);QTextCodec *code = QTextCodec::codecForName("GBK");QString str = code->toUnicode(newValue);ui->textBrowser->append(str.toUtf8());
}//描述符成功被写
void MWidget::mDescriptorWritten(QLowEnergyDescriptor descriptor, QByteArray newValue)
{ui->textBrowser->append(descriptor.uuid().toString()+":"+newValue);ui->textBrowser->append("描述符写入成功");
}void MWidget::on_pushButton_clicked()
{QString text = ui->lineEdit->text();QTextCodec *code = QTextCodec::codecForName("GBK");QString str = code->toUnicode(text.toUtf8());mService->writeCharacteristic(charList.at(0),str.toUtf8());
}
四、与ECB02模块通信效果
(1)连接效果
(2)写描述符,激活notify效果