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

概述

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

大致的连接步骤是:

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

界面设计


代码设计

主界面的.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 <QMainWindow>
#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<QLowEnergyCharacteristic> list=m_service->characteristics();

                        for(int i=0;i<list.count();i++)
                        {
                            this->m_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() << "连接失败:" <<error;
//    });

}


BluetoothConnect::~BluetoothConnect()
{
    delete ui;
}
#ifndef BLUETOOTHCONNECT_H
#define BLUETOOTHCONNECT_H

#include <QMainWindow>
#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<QBluetoothDeviceInfo> devInfos;
    QList<QBluetoothUuid> 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 <QWidget>
#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

运行演示

 欢迎关注小徐的个人微信公众号,感觉微信的文章排版不错,后续会继续分享一些新的学习记录~

  • 52
    点赞
  • 240
    收藏
    觉得还不错? 一键收藏
  • 46
    评论
IntelliJ IDEA2021是一款功能强大的集成开发环境,用于Java开发。它提供了许多便捷的功能和工具,以提高开发效率并提供良好的用户体验。 在配置Maven时,可以按照以下步骤进行操作: 1. 下载Apache Maven。Maven是Java的项目管理工具,可以帮助我们管理项目依赖和构建过程。你可以从官方网站下载最新版本的Maven。 2. 打开IntelliJ IDEA并进入设置界面。你可以通过点击菜单栏中的 "File",然后选择 "Settings" 或者使用快捷键 "Ctrl + Alt + S" 打开设置界面。 3. 在设置界面中,选择 "Build, Execution, Deployment",然后选择 "Build Tools",接着选择 "Maven"。 4. 点击右侧的 "+" 按钮,添加Maven安装的路径。确保选择正确的路径,并点击 "OK"。 5. 在 "Maven" 设置界面中,你可以配置一些其他的选项,例如本地存储库的路径和远程仓库的设置。根据需要进行相应的配置,并点击 "Apply" 或 "OK" 保存更改。 通过以上步骤,你就可以成功配置Maven,并在IntelliJ IDEA中使用它来管理你的Java项目了。希望对你有所帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [2021 最新 IntelliJ IDEA 详细配置步骤演示(图文版)](https://blog.csdn.net/qq_44866828/article/details/121869104)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Intellij IDEA 2021 Maven 配置指南](https://blog.csdn.net/m0_46491549/article/details/119594094)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 46
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值