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.总结
关于一些延时的处理,发现运行时会出现崩溃的问题,因此加入了一些延时。最后附上一张完整执行过程。
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。