Qt开发简易蓝牙调试助手(低功耗蓝牙)

概述

Qt中是有蓝牙模块的,直接用此模块开发就行。但是注意使用的是低功耗蓝牙的类,连接方式和经典蓝牙会有区别

大致的连接步骤是:

  1. 搜索附近的蓝牙设备
  2. 连接指定的蓝牙设备
  3. 获取服务
  4. 指定服务进行连接(因为每一种下的特征对象的权限是不一样的,有的只有读取权限,没有写权限,有的则相反,必要时可以直接打印一下查看)
  5. 获取服务下可用的特征对象
  6. 监听特征对象的消息变化和向特征对象发送消息

界面设计

Qt开发简易蓝牙调试助手(低功耗蓝牙)_第1张图片

Qt开发简易蓝牙调试助手(低功耗蓝牙)_第2张图片


代码设计

主界面的.cpp和.h

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QBluetoothLocalDevice"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //连接设备按钮点击事件
    this->btConnect = new BluetoothConnect();
    connect(ui->btnConnectDevice,&QPushButton::clicked,[=](){
        //this->hide();
        btConnect->show();
    });

    //监听连接设备窗口发送的连接服务信号
    connect(btConnect,&BluetoothConnect::toConectCharacteristic,this,&MainWindow::ConnectCharacteristic);

    //数据发送按钮点击事件
    connect(ui->btnSend,&QPushButton::clicked,[=](){
        //发送数据
        btConnect->m_service->writeCharacteristic(btConnect->m_characteristic,ui->leSendData->text().toUtf8(),QLowEnergyService::WriteMode::WriteWithoutResponse);
    });

    //关闭数据接收按钮点击事件
    connect(ui->btnClose,&QPushButton::clicked,[=](){
        if(this->isClose)
        {
            ui->btnClose->setText("开启");
            this->isClose = false;
        }
        else
        {
             ui->btnClose->setText("关闭");
             this->isClose = true;
        }
    });

    //清除数据接受区内容按钮点击事件
    connect(ui->btnClear,&QPushButton::clicked,[=](){
        ui->tbRevData->clear();
    });
}

void MainWindow::ConnectCharacteristic(QLowEnergyService * m_service)
{
    // 通过监听特征对象的变化
    //写的和读取到的都会进入到这个位置
    connect(m_service,&QLowEnergyService::characteristicChanged,[=](QLowEnergyCharacteristic c,QByteArray value) {
//        qDebug() << "characteristicChanged state change::";
//        qDebug() << "value length::" << value.length();
//        qDebug() << "value length::" << value;
        if(this->isClose)
        {
            ui->tbRevData->append(value);
        }
    });

    //没有写响应属性的Characteristic不会进入这个连接
//    connect(m_service,&QLowEnergyService::characteristicWritten,[=](QLowEnergyCharacteristic c,QByteArray value) {
        qDebug() << "characteristicChanged state change::";
        qDebug() << "value length::" << value.length();
        qDebug() << "value length::" << value;
//    });

    //service错误监听
    connect(m_service,&QLowEnergyService::errorOccurred,[=](QLowEnergyService::ServiceError newErrorr){
        if(QLowEnergyService::NoError == newErrorr)
            {
                  qDebug() <<"没有发生错误。";
            }
            if(QLowEnergyService::OperationError==newErrorr)
            {
                 qDebug() <<"错误: 当服务没有准备好时尝试进行操作!";
            }
            if(QLowEnergyService::CharacteristicReadError==newErrorr)
            {
                 qDebug() <<"尝试读取特征值失败!";
            }
            if(QLowEnergyService::CharacteristicWriteError==newErrorr)
            {
                 qDebug() <<"尝试为特性写入新值失败!";
            }
            if(QLowEnergyService::DescriptorReadError==newErrorr)
            {
                 qDebug() <<"尝试读取描述符值失败!";
            }
            if(QLowEnergyService::DescriptorWriteError==newErrorr)
            {
                 qDebug() <<" 尝试向描述符写入新值失败!";
            }
            if(QLowEnergyService::UnknownError==newErrorr)
            {
                 qDebug() <<"与服务交互时发生未知错误!";
            }

    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include "bluetoothconnect.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    BluetoothConnect *btConnect;
    bool isClose = true;

    void ConnectCharacteristic(QLowEnergyService * m_service);

private:
    Ui::MainWindow *ui;

};
#endif // MAINWINDOW_H

连接界面的.cpp和.h

#include "bluetoothconnect.h"
#include "ui_bluetoothconnect.h"



BluetoothConnect::BluetoothConnect(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::BluetoothConnect)
{
    ui->setupUi(this);

    //设置设备列表的标题
    QListWidgetItem *item = new QListWidgetItem();
    //创建自定义的窗口 然后放入到listwidget中
    BtDevCell *bdc = new BtDevCell();
    //设置item的高
    item->setSizeHint(QSize(ui->lwShow->width(),bdc->height()));
    //设置label的显示
    bdc->btName->setText("名称");
    bdc->btAddr->setText("地址");
    bdc->btRssi->setText("信号强度");

    //把item加入到listwidget
    ui->lwShow->addItem(item);
    //设置item的窗口为自定义的窗口
    ui->lwShow->setItemWidget(item,bdc);

    //设置服务列表的标题
    QListWidgetItem *items = new QListWidgetItem();
    //创建自定义的窗口 然后放入到listwidget中
    BtDevCell *bdcs = new BtDevCell();
    //把item加入到listwidget
    items->setSizeHint(QSize(ui->lwService->width(),bdcs->height()));
    //设置label的显示
    bdcs->btName->setText("空");
    bdcs->btAddr->setText("服务Uuid");
    bdcs->btRssi->setText("空");
    //设置item的窗口为自定义的窗口
    ui->lwService->addItem(items);
    //设置item的窗口为自定义的窗口
    ui->lwService->setItemWidget(items,bdcs);

    //创建通信的socket 普通蓝牙使用
    //QBluetoothSocket *btSocket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol,this);


    //创建设备发现对象
    QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);

    //点击搜索设备后开始搜索设备
    connect(ui->btnSerachDevice,&QPushButton::clicked,[=](){
        qDebug() << "开始搜索设备";
        //如果已经搜索过一次了,那么设计列表可能就大于1,那么就清空设备列表
        //但是标题也会被清除,所以重新构建
        if(ui->lwShow->count()>1)
        {
            ui->lwShow->clear();

            //设置设备列表的标题
            QListWidgetItem *item = new QListWidgetItem();
            //创建自定义的窗口 然后放入到listwidget中
            BtDevCell *bdc = new BtDevCell();
            //设置item的高
            item->setSizeHint(QSize(ui->lwShow->width(),bdc->height()));
            //设置label的显示
            bdc->btName->setText("名称");
            bdc->btAddr->setText("地址");
            bdc->btRssi->setText("信号强度");

            //把item加入到listwidget
            ui->lwShow->addItem(item);
            //设置item的窗口为自定义的窗口
            ui->lwShow->setItemWidget(item,bdc);
        }

        //开始搜索设备
        discoveryAgent->start();

    });

    //搜索到设备后进入
    connect(discoveryAgent,&QBluetoothDeviceDiscoveryAgent::deviceDiscovered,[=](QBluetoothDeviceInfo devInfo){
        qDebug() << "搜索到设备";
        //名称不为空且是低功耗蓝牙
        if(devInfo.name() != "" && (devInfo.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration))
        {
            QListWidgetItem *item = new QListWidgetItem();
            BtDevCell *bdc = new BtDevCell();

            item->setSizeHint(QSize(ui->lwShow->width(),bdc->height()));

            bdc->btName->setText(devInfo.name());
            bdc->btAddr->setText(devInfo.address().toString());
            bdc->btRssi->setText(QString::number(devInfo.rssi()));

            ui->lwShow->addItem(item);
            ui->lwShow->setItemWidget(item,bdc);

            devInfos.append(devInfo);
        }
    });

    //搜索设备发生错误
    connect(discoveryAgent,&QBluetoothDeviceDiscoveryAgent::errorOccurred,[=](QBluetoothDeviceDiscoveryAgent::Error error){
        qDebug() << error;
        //警告对话框
        QMessageBox::warning(this,"警告","搜索蓝牙设备发生错误,请检查蓝牙是否开启!");
    });

    //搜索设备完成
    connect(discoveryAgent,&QBluetoothDeviceDiscoveryAgent::finished,[=](){
        qDebug() << "搜索完成";
    });

    //设备列表被点击事件
    connect(ui->lwShow,&QListWidget::itemClicked,[=](QListWidgetItem *item){
        //这是经典蓝牙的连接方式
//        QWidget *widget = ui->lwShow->itemWidget(item);
//        BtDevCell *wbdc = (BtDevCell *)widget;
//        qDebug() << wbdc->btAddr->text().toUtf8().data();
//        btSocket->connectToService(QBluetoothAddress(wbdc->btAddr->text().toUtf8().data()),QBluetoothUuid("00001101-0000-1000-8000-00805F9B34FB"),QIODevice::ReadWrite);

        //这是低功耗蓝牙的连接方式
        //qDebug() << ui->lwShow->currentRow();
        //创建蓝牙控制器
        QLowEnergyController *lowBtControl = QLowEnergyController::createCentral(this->devInfos.at(ui->lwShow->currentRow()-1));
        //连接设备
        lowBtControl->connectToDevice();

        //连接成功后进入
        connect(lowBtControl,&QLowEnergyController::connected,[=](){
                qDebug() << "连接成功";
                //搜索服务
                lowBtControl->discoverServices();

        });

        //连接失败后进入
        connect(lowBtControl,&QLowEnergyController::errorOccurred,[=](QLowEnergyController::Error newError){
                qDebug() << newError;
        });

        //搜索到服务后进入
        connect(lowBtControl,&QLowEnergyController::serviceDiscovered, [=](QBluetoothUuid serviceUuid) {
            qDebug() << "发现服务";

            QListWidgetItem *item = new QListWidgetItem();
            BtDevCell *bdc = new BtDevCell();

            item->setSizeHint(QSize(ui->lwService->width(),bdc->height()));

            bdc->btName->setText("");
            bdc->btAddr->setText(serviceUuid.toString());
            bdc->btRssi->setText("");

            ui->lwService->addItem(item);
            ui->lwService->setItemWidget(item,bdc);

            btUuids.append(serviceUuid);
        });

        //服务uuid列表被点击事件
        connect(ui->lwService,&QListWidget::itemClicked,[=](){
            QBluetoothUuid serviceUuid = btUuids.at(ui->lwService->currentRow()-1);
            //创建服务
            this->m_service = lowBtControl->createServiceObject(QBluetoothUuid(serviceUuid),this);
            if(m_service==NULL)
            {
                qDebug() << "服务建立失败!";
            }
            else
            {
                qDebug() << "服务建立成功!";

                // 服务对象创建成功后,坚挺服务状态变化,如果状态变成已发现,则进行后续服务下特征对象获取
                connect(m_service,&QLowEnergyService::stateChanged, this, [this]() {
                    //qDebug() << "service state change" << m_service->state();
                    //发现服务, 建立characteristic对象实例
                    if(m_service->state() == QLowEnergyService::ServiceDiscovered) {

                        //获取特征对象
                        QList list=m_service->characteristics();

                        for(int i=0;im_characteristic = list.at(i);

                            //qDebug() << c.properties();
                            /*如果QLowEnergyCharacteristic对象有效,则返回true,否则返回false*/
                            if(m_characteristic.isValid())
                            {
                                //描述符定义特征如何由特定客户端配置。
                                QLowEnergyDescriptor m_notificationDesc = m_characteristic.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);
                                if(m_notificationDesc.isValid())
                                {
                                    //写描述符
                                    m_service->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0100"));
                                    //m_service->writeDescriptor(m_notificationDesc, QByteArray::fromHex("FEE1"));
                                }
                            }
                        }
                    }
                });

                //通知主窗口可以连接service了
                emit toConectCharacteristic(m_service);

                // 触发服务详情发现函数 ,不要忘记调用
                m_service->discoverDetails();
            }
        });
    });

//    //普通蓝牙使用
//    connect(btSocket,&QBluetoothSocket::connected,[=](){
//        qDebug() << "连接完成";
//    });

//    connect(btSocket,&QBluetoothSocket::errorOccurred,[=](QBluetoothSocket::SocketError error){
//        qDebug() << "连接失败:" <
#ifndef BLUETOOTHCONNECT_H
#define BLUETOOTHCONNECT_H

#include 
#include "QLowEnergyController"
#include "QBluetoothLocalDevice"
#include "QBluetoothDeviceDiscoveryAgent"
#include "QBluetoothSocket"
#include "QDebug"
#include "QListWidgetItem"
#include "btdevcell.h"
#include "QLabel"
#include "QMessageBox"
#include "QLowEnergyDescriptor"
#include "QLowEnergyService"
#include "QBluetoothUuid"
#include "QTimer"

namespace Ui {
class BluetoothConnect;
}

class BluetoothConnect : public QMainWindow
{
    Q_OBJECT

public:
    explicit BluetoothConnect(QWidget *parent = nullptr);
    ~BluetoothConnect();

    QList devInfos;
    QList btUuids;

    QLowEnergyService * m_service;
    QLowEnergyCharacteristic m_characteristic;

    void searchCharacteristic();

private:
    Ui::BluetoothConnect *ui;

signals:
    void toConectCharacteristic(QLowEnergyService * m_service);

};

#endif // BLUETOOTHCONNECT_H

listWidget Item界面.cpp和.h

#include "btdevcell.h"
#include "ui_btdevcell.h"

BtDevCell::BtDevCell(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::BtDevCell)
{
    ui->setupUi(this);

    this->btName = ui->btName;
    this->btAddr = ui->btAddr;
    this->btRssi = ui->btRssi;
}

BtDevCell::~BtDevCell()
{
    delete ui;
}
#ifndef BTDEVCELL_H
#define BTDEVCELL_H

#include 
#include "QLabel"

namespace Ui {
class BtDevCell;
}

class BtDevCell : public QWidget
{
    Q_OBJECT

public:
    explicit BtDevCell(QWidget *parent = nullptr);
    ~BtDevCell();
    QLabel *btName;
    QLabel *btAddr;
    QLabel *btRssi;

private:
    Ui::BtDevCell *ui;

};

#endif // BTDEVCELL_H

运行演示

Qt开发简易蓝牙调试助手(低功耗蓝牙)_第3张图片

Qt开发简易蓝牙调试助手(低功耗蓝牙)_第4张图片

你可能感兴趣的:(Qt学习,qt,单片机,开发语言)