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

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

#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设备

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

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.总结

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

好的,我可以回答这个问题。以下是使用 Qt 编写低功耗蓝牙 BLE 的示例代码: 首先,需要在 Qt 项目中添加 Bluetooth 模块。在 .pro 文件中添加以下行: QT += bluetooth 然后,在代码中包含 Bluetooth 头文件: #include <QBluetoothDeviceDiscoveryAgent> #include <QBluetoothLocalDevice> #include <QBluetoothServiceDiscoveryAgent> #include <QBluetoothSocket> 接下来,可以使用 QBluetoothLocalDevice 类来获取本地设备的信息,例如设备名称和地址: QBluetoothLocalDevice localDevice; QString localDeviceName = localDevice.name(); QString localDeviceAddress = localDevice.address().toString(); 然后,可以使用 QBluetoothDeviceDiscoveryAgent 类来搜索附近的 BLE 设备: QBluetoothDeviceDiscoveryAgent discoveryAgent; connect(&discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(deviceDiscovered(QBluetoothDeviceInfo))); discoveryAgent.start(); 在 deviceDiscovered() 槽函数中,可以获取搜索到的设备信息: void MyClass::deviceDiscovered(const QBluetoothDeviceInfo &device) { qDebug() << "Discovered device:" << device.name() << device.address().toString(); } 接下来,可以使用 QBluetoothServiceDiscoveryAgent 类来搜索设备上的服务: QBluetoothServiceDiscoveryAgent discoveryAgent(device.address()); connect(&discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); discoveryAgent.start(); 在 serviceDiscovered() 槽函数中,可以获取搜索到的服务信息: void MyClass::serviceDiscovered(const QBluetoothServiceInfo &service) { qDebug() << "Discovered service:" << service.serviceName() << service.serviceUuid().toString(); } 最后,可以使用 QBluetoothSocket 类来连接设备并发送数据: QBluetoothSocket socket(QBluetoothServiceInfo::RfcommProtocol); socket.connectToService(service); socket.write("Hello, world!"); 以上就是使用 Qt 编写低功耗蓝牙 BLE 的示例代码。希望对你有帮助!
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值