时间记录: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_NAMESPACE
class MWidget : public QWidget
{
Q_OBJECT
public:
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效果