当前位置:首页 » 《关于电脑》 » 正文

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

27 人参与  2024年04月20日 10:55  分类 : 《关于电脑》  评论

点击全文阅读


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

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


点击全文阅读


本文链接:http://zhangshiyu.com/post/97897.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1