Qt笔记---使用Qt开发低功耗蓝牙BLE(Bluetooth low energy)程序

Black_zy 2024-08-21 11:35:01 阅读 91

Qt笔记---使用Qt开发BLE(Bluetooth low energy)程序

在Qt项目中开发BLE通信程序,即低功耗蓝牙设备通信,关于蓝牙设备的通信分为普通蓝牙设备和低功耗蓝牙设备,此文只介绍低功耗蓝牙设备的连接通信方式。

开发环境:

系统:win10

Qt:5.15.2

MSVC:2019

注:使用此版本之前使用过其他低版本的Qt和MSVC,会出现搜索不到设备以及一些各种其他的问题,最后使用此版本功能正常。

使用方法

1.在工程的pro文件中添加对蓝牙模块的支持

QT += bluetooth

2.开始扫描发现设备

扫描BLE设备需要用到QBluetoothDeviceDiscoveryAgent类,通过start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)函数发现低功耗设备。将扫描出的设备信息放到链表中。

BluetoothDeviceService.h

<code>#include <QBluetoothLocalDevice>

#include <QBluetoothDeviceDiscoveryAgent>

#include <QLowEnergyController>

class BluetoothDeviceService : public QObject

{

Q_OBJECT

public:

explicit BluetoothDeviceService(QObject *parent = nullptr);

private slots:

// 发现的BLE设备信息

void onDeviceDiscovered(const QBluetoothDeviceInfo &deviceInfo);

// 搜索设备时出错

void onDeviceDiscoverError(QBluetoothDeviceDiscoveryAgent::Error error);

private:

// 设备发现对象

QBluetoothDeviceDiscoveryAgent *m_deviceDiscoveryAgent;

// 保存发现的BLE设备信息

QList<QBluetoothDeviceInfo> *m_deviceInfoList;

// 保存服务的uuid

QList<QBluetoothUuid> m_uuidList;

// 蓝牙控制器

QLowEnergyController *m_control;

// 控制器连接计时器

QTimer m_controlTimer;

// 蓝牙服务

QLowEnergyService *m_service;

QList<QLowEnergyCharacteristic> m_charList;

QLowEnergyCharacteristic m_character;

QLowEnergyDescriptor m_descriptor;

};

BluetoothDeviceService.cpp

#include "BluetoothDeviceService.h"

BluetoothDeviceService::BluetoothDeviceService(QObject *parent)

: QObject{parent},

m_control(NULL),

m_service(NULL)

{

m_deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);

m_deviceInfoList = new QList<QBluetoothDeviceInfo>();

// 设置搜索设备超时 20s

m_deviceDiscoveryAgent->setLowEnergyDiscoveryTimeout(20000);

connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,

this, &BluetoothDeviceService::onDeviceDiscovered);

connect(m_deviceDiscoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(onDeviceDiscoverError(QBluetoothDeviceDiscoveryAgent::Error)));

connect(&m_controlTimer, &QTimer::timeout, [this](){

emit sigDebugLog(QString::fromLocal8Bit("蓝牙控制器连接设备超时!"));

disconnectDevice();

});

}

void BluetoothDeviceService::onDeviceDiscovered(const QBluetoothDeviceInfo &deviceInfo)

{

if (deviceInfo.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration)

{

// 添加对发现的BLE设备名称过滤,只保留需要名称的设备

if (deviceInfo.name().contains(QString::fromLocal8Bit("过滤名称")))

{

emit sigDebugLog(QString::fromLocal8Bit("发现一个蓝牙设备:%1--地址:%2").arg(deviceInfo.name()).arg(deviceInfo.address().toString()));

// 保存设备信息

m_deviceInfoList->append(deviceInfo);

emit sigDiscovered(deviceInfo);

}

}

}

void BluetoothDeviceService::disconnectDevice()

{

if(m_controlTimer.isActive())

m_controlTimer.stop();

if(m_control) {

m_control->disconnectFromDevice();

delete m_control;

m_control = NULL;

}

if(m_service){

delete m_service;

m_service = NULL;

}

}

3.连接指定的BLE设备

通过双击界面上的设备列表,将设备列表的索引传到设备信息链表中,创建对应的蓝牙控制器。

<code>void BluetoothDeviceService::connectDevice(int iRow)

{

// 只保存当前选中设备的服务uuid,删除其他

m_uuidList.clear();

//创建蓝牙控制器对象

m_control = QLowEnergyController::createCentral(m_deviceInfoList->at(iRow));

if (m_control == NULL)

{

emit sigDebugLog(QString::fromLocal8Bit("创建蓝牙控制器失败!"));

}

else

{

emit sigDebugLog(QString::fromLocal8Bit("创建蓝牙控制器成功!"));

}

connect(m_control, SIGNAL(connected()), this, SLOT(onControlConnected()));

connect(m_control, SIGNAL(disconnected()), this, SLOT(onControlDisconnected()));

connect(m_control, SIGNAL(serviceDiscovered(QBluetoothUuid)), this, SLOT(onServiceDiscovered(QBluetoothUuid)));

connect(m_control, SIGNAL(discoveryFinished()), this, SLOT(onControlDiscoveryFinished()));

connect(m_control, SIGNAL(error(QLowEnergyController::Error)), this, SLOT(onControlError(QLowEnergyController::Error)));

// 开始计时控制器的连接超时

m_controlTimer.start(10000);

// 发起连接

m_control->connectToDevice();

}

4.发现蓝牙服务

发现蓝牙服务要在蓝牙控制器连接成功后进行,在搜索服务之前做了1秒的延时处理。

void BluetoothDeviceService::onControlConnected()

{

// 停止连接计时

m_controlTimer.stop();

emit sigDebugLog(QString::fromLocal8Bit("蓝牙控制器连接成功,开始搜索蓝牙服务!"));

m_uuidList.clear();

QThread::msleep(1000);

//搜索服务

m_control->discoverServices();

}

5.发现蓝牙服务后保存其服务uuid

void BluetoothDeviceService::onServiceDiscovered(const QBluetoothUuid &newService)

{

emit sigDebugLog(QString::fromLocal8Bit("发现一个蓝牙服务-uuid:").append(newService.toString()));

m_uuidList.append(newService);

}

6.创建蓝牙服务

在发现蓝牙服务结束后,延时创建蓝牙服务。蓝牙服务创建成功以后开始获取服务详情,也加了延时。

void BluetoothDeviceService::onControlDiscoveryFinished()

{

emit sigDebugLog(QString::fromLocal8Bit("蓝牙服务搜索结束!"));

QThread::msleep(1000);

createService(0);

}

void BluetoothDeviceService::createService(int iRow)

{

// 创建服务

m_service = m_control->createServiceObject(m_uuidList.at(iRow),this);

if (m_service == NULL)

{

emit sigDebugLog(QString::fromLocal8Bit("创建蓝牙服务失败!"));

} else {

emit sigDebugLog(QString::fromLocal8Bit("创建蓝牙服务成功!"));

//监听服务状态变化

connect(m_service,SIGNAL(stateChanged(QLowEnergyService::ServiceState))

,this,SLOT(onServiceStateChanged(QLowEnergyService::ServiceState)));

//服务的characteristic变化,有数据传来

connect(m_service,SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray))

,this,SLOT(onServiceCharacteristicChanged(QLowEnergyCharacteristic,QByteArray)));

//描述符成功被写

connect(m_service,SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray))

,this,SLOT(onDescriptorWritten(QLowEnergyDescriptor,QByteArray)));

//

connect(m_service, SIGNAL(error(QLowEnergyService::ServiceError)), this, SLOT(onServiceError(QLowEnergyService::ServiceError)));

QThread::msleep(1000);

//服务详情发现函数

m_service->discoverDetails();

}

}

7.在发现蓝牙服务后,对每个特征进行处理,包括配置描述符和存储具有写入权限的特征。

void BluetoothDeviceService::onServiceStateChanged(QLowEnergyService::ServiceState newState)

{

Q_UNUSED(newState);

QLowEnergyCharacteristic bleCharacteristic;

//发现服务

if(m_service->state() == QLowEnergyService::ServiceDiscovered){

m_charList = m_service->characteristics();

for(int i=0; i<m_charList.size(); i++){

bleCharacteristic = m_charList.at(i);

if(bleCharacteristic.isValid()){

m_descriptor = bleCharacteristic.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);

if(m_descriptor.isValid()){

m_service->writeDescriptor(m_descriptor,QByteArray::fromHex("0100"));

}

if (bleCharacteristic.properties() & QLowEnergyCharacteristic::WriteNoResponse || bleCharacteristic.properties() & QLowEnergyCharacteristic::Write)

{

m_character = bleCharacteristic;

}

}

}

}

}

8.接收数据

void BluetoothDeviceService::onServiceCharacteristicChanged(QLowEnergyCharacteristic characteristic, QByteArray newValue)

{

Q_UNUSED(characteristic);

int len = newValue.size();

if(len > 0){

emit sigDebugLog(QString("rec:").append(newValue.toHex()));

}

}

9.发送数据

void BluetoothDeviceService::sendCmd(const QByteArray &data)

{

if (m_service)

{

m_service->writeCharacteristic(m_character, data, QLowEnergyService::WriteWithResponse);

}

}

10.总结

关于一些延时的处理,发现运行时会出现崩溃的问题,因此加入了一些延时。最后附上一张完整执行过程。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。