QT开发低功耗蓝牙BLE连接ECB02模块进行数据收发

时间记录:2024/1/22

一、注意点

(1)pro文件中引入bluetooth模块
(2)安卓端运行时需要同步打开定位功能才能扫描到蓝牙设备
(3)mingw套件不能在Windows上运行,需要使用MSVC套件编译才能在Windows上运行

二、使用步骤

(1)设备蓝牙操作类QBluetoothLocalDevice
    2.1.1 hostMode方法获取蓝牙打开状态
    2.1.2 powerOn方法打开蓝牙
    2.1.3 setHostMode方法关闭蓝牙
(2)蓝牙设备搜索类QBluetoothDeviceDiscoveryAgent
    2.2.1 setLowEnergyDiscoveryTimeout方法设置扫描超时时间,如果设置为0,则一直进行扫描
    2.2.2 为QBluetoothDeviceDiscoveryAgent对象的deviceDiscovered信号绑定槽,每发现一台蓝牙设备便会触发一次此信号,携带参数QBluetoothDeviceInfo,每台蓝牙设备的信息类
    2.2.3 使用start方法,开始搜索蓝牙设备,参数可以传递QBluetoothDeviceDiscoveryAgent::LowEnergyMethod表示搜索低功耗蓝牙设备
(3)低功耗蓝牙控制器类QLowEnergyController
    2.3.1 使用静态方法createCentral创建蓝牙控制器对象,参数为QBluetoothDeviceInfo对象
    2.3.2 为serviceDiscovered信号绑定槽,每发现一个服务触发一次此信号,携带参数QBluetoothUuid
    2.3.3 为connected信号绑定槽,用于判断是否已成功连接到蓝牙
    2.3.4 使用connectToDevice方法连接蓝牙
    2.3.5 使用disconnectFromDevice方法来断开连接
    2.3.6 连接成功后调用discoverServices方法获取连接蓝牙下的所有服务
(4)低功耗蓝牙服务类QLowEnergyService
    2.4.1 使用QLowEnergyController对象的createServiceObject方法创建QLowEnergyService对象
    2.4.2 为stateChanged信号绑定槽,监听服务状态
    2.4.3 为characteristicChanged信号绑定槽,收到信息时会触发此信号,信息为携带的参数newValue
    2.4.4 为descriptorWritten信号绑定槽,监听描述符是否成功写入
    2.4.5 使用discoverDetails方法获取服务详情
    2.4.6 服务状态改变以后写入描述符激活notify,否则无法收到消息,使用characteristics方法获取服务下所有的特征对象
(5)低功耗蓝牙特征值类QLowEnergyCharacteristic
    2.5.1 遍历特征值对象列表,使用isValid方法判断是否可用
    2.5.2 使用descriptor方法创建描述符对象,参数传递QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration,表示描述符类型由客户端特征值自行配置
(6)低功耗蓝牙描述符对象QLowEnergyDescriptor
    2.6.1 使用isValid方法判断描述符对象是否有效
    2.6.2 使用QLowEnergyService类的writeDescriptor方法向蓝牙写入描述符,激活notify,参数第一个为描述符对象,第二个为QByteArray::fromHex(“0100”)
(7)使用QLowEnergyService类的writeCharacteristic方法写入数据

三、参考代码

(1)头文件

#ifndef MWIDGET_H
#define MWIDGET_H#include <QWidget>
#include <QBluetoothDeviceDiscoveryAgent> //蓝牙设备搜索对象
#include <QBluetoothLocalDevice> //本机蓝牙操作
#include <QBluetoothDeviceInfo>
#include <QList>
#include <QListWidgetItem>
#include <QLowEnergyController> //蓝牙控制器对象
#include <QBluetoothUuid>
#include <QLowEnergyService>
#include <QLowEnergyCharacteristic>
#include <QByteArray>//static const QLatin1String serviceUUID("0000FFF0-0000-1000-8000-00805F9B34FB");
//static const QLatin1String readUUID("0000FFF1-0000-1000-8000-00805F9B34FB");
//static const QLatin1String writeUUID("0000FFF2-0000-1000-8000-00805F9B34FB");QT_BEGIN_NAMESPACE
namespace Ui { class MWidget; }
QT_END_NAMESPACEclass MWidget : public QWidget
{Q_OBJECTpublic:MWidget(QWidget *parent = nullptr);~MWidget();private:Ui::MWidget *ui;QBluetoothDeviceDiscoveryAgent *deviceDiscoveryAgent;QBluetoothLocalDevice *localDevice;QList<QBluetoothDeviceInfo> *deviceInfoList;QList<QBluetoothUuid> uuidList;QLowEnergyController *control;QLowEnergyService *mService;QLowEnergyCharacteristic mCharacter;QList<QLowEnergyCharacteristic> charList;private slots:void mDeviceDiscovered(QBluetoothDeviceInfo deviceInfo);void on_openLocalDeviceBtn_clicked();void on_closeLocalDeviceBtn_clicked();void on_searchBtn_clicked();void on_listWidget_itemDoubleClicked(QListWidgetItem *item);void mServiceDiscovered(QBluetoothUuid serviceUuid);void mConnected();void on_uuidListWidget_itemDoubleClicked(QListWidgetItem *item);void mStateChanged(QLowEnergyService::ServiceState newState);void mCharacteristicChanged(QLowEnergyCharacteristic characteristic,QByteArray newValue);void mDescriptorWritten(QLowEnergyDescriptor descriptor,QByteArray newValue);void on_pushButton_clicked();
};
#endif // MWIDGET_H

(2)源文件

#include "mwidget.h"
#include "ui_mwidget.h"
#include <QTextCodec>MWidget::MWidget(QWidget *parent): QWidget(parent), ui(new Ui::MWidget)
{ui->setupUi(this);this->setLayout(ui->verticalLayout_2);//创建对象deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);localDevice = new QBluetoothLocalDevice(this);deviceInfoList = new QList<QBluetoothDeviceInfo>();deviceDiscoveryAgent->setLowEnergyDiscoveryTimeout(5000);//连接槽connect(deviceDiscoveryAgent,SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),this,SLOT(mDeviceDiscovered(QBluetoothDeviceInfo)));
}MWidget::~MWidget()
{delete ui;
}//蓝牙设备发现槽
void MWidget::mDeviceDiscovered(QBluetoothDeviceInfo deviceInfo)
{//如果名称不为空切为低功耗蓝牙if(deviceInfo.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration){QString label = QString("%1 %2").arg(deviceInfo.name()).arg(deviceInfo.address().toString());ui->listWidget->addItem(label);deviceInfoList->append(deviceInfo);}
}//打开本地蓝牙
void MWidget::on_openLocalDeviceBtn_clicked()
{if(localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff){localDevice->powerOn();}
}//关闭本地蓝牙
void MWidget::on_closeLocalDeviceBtn_clicked()
{localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
}void MWidget::on_searchBtn_clicked()
{ui->listWidget->clear();deviceInfoList->clear();deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
}//双击连接设备
void MWidget::on_listWidget_itemDoubleClicked(QListWidgetItem *item)
{deviceDiscoveryAgent->stop();Q_UNUSED(item);uuidList.clear();//创建蓝牙控制器对象control = QLowEnergyController::createCentral(deviceInfoList->at(ui->listWidget->currentRow()));connect(control,SIGNAL(serviceDiscovered(QBluetoothUuid)),this,SLOT(mServiceDiscovered(QBluetoothUuid)));connect(control,SIGNAL(connected()),this,SLOT(mConnected()));control->connectToDevice();
}//发现服务uuid
void MWidget::mServiceDiscovered(QBluetoothUuid serviceUuid)
{QString label = QString("%1").arg(serviceUuid.toString());ui->uuidListWidget->addItem(label);uuidList.append(serviceUuid);
}//成功连接到设备
void MWidget::mConnected()
{ui->textBrowser->append("成功连接"+deviceInfoList->at(ui->listWidget->currentRow()).name());//搜索服务uuidList.clear();control->discoverServices();
}//双击创建服务UUID,写描述符,建立通讯
void MWidget::on_uuidListWidget_itemDoubleClicked(QListWidgetItem *item)
{Q_UNUSED(item);//创建服务mService = control->createServiceObject(uuidList.at(ui->uuidListWidget->currentRow()),this);if(mService == NULL){ui->textBrowser->append("创建服务失败");}else{ui->textBrowser->append("服务创建成功");ui->comboBox->clear();//监听服务状态变化connect(mService,SIGNAL(stateChanged(QLowEnergyService::ServiceState)),this,SLOT(mStateChanged(QLowEnergyService::ServiceState)));//服务的characteristic变化,有数据传来connect(mService,SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)),this,SLOT(mCharacteristicChanged(QLowEnergyCharacteristic,QByteArray)));//描述符成功被写connect(mService,SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray)),this,SLOT(mDescriptorWritten(QLowEnergyDescriptor,QByteArray)));//服务详情发现函数mService->discoverDetails();}
}//服务状态改变
void MWidget::mStateChanged(QLowEnergyService::ServiceState newState)
{Q_UNUSED(newState);//发现服务if(mService->state() == QLowEnergyService::ServiceDiscovered){charList = mService->characteristics();for(int i=0;i<charList.size();i++){mCharacter = charList.at(i);if(mCharacter.isValid()){ui->comboBox->addItem(mCharacter.uuid().toString());QLowEnergyDescriptor descriptor = mCharacter.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);if(descriptor.isValid()){mService->writeDescriptor(descriptor,QByteArray::fromHex("0100"));}}}}
}//characteristic变化,数据传来
void MWidget::mCharacteristicChanged(QLowEnergyCharacteristic characteristic, QByteArray newValue)
{ui->textBrowser->append("接收值成功");Q_UNUSED(characteristic);QTextCodec *code = QTextCodec::codecForName("GBK");QString str = code->toUnicode(newValue);ui->textBrowser->append(str.toUtf8());
}//描述符成功被写
void MWidget::mDescriptorWritten(QLowEnergyDescriptor descriptor, QByteArray newValue)
{ui->textBrowser->append(descriptor.uuid().toString()+":"+newValue);ui->textBrowser->append("描述符写入成功");
}void MWidget::on_pushButton_clicked()
{QString text = ui->lineEdit->text();QTextCodec *code = QTextCodec::codecForName("GBK");QString str = code->toUnicode(text.toUtf8());mService->writeCharacteristic(charList.at(0),str.toUtf8());
}

四、与ECB02模块通信效果

(1)连接效果
连接效果
(2)写描述符,激活notify效果
激活notify效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/423166.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode56. 合并区间

文章目录 题目原题链接思路代码 题目 以数组intervals表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; …

yolov5 opencv dnn部署自己的模型

yolov5 opencv dnn部署自己的模型 github开源代码地址使用github源码结合自己导出的onnx模型推理自己的视频推理条件c部署c 推理结果 github开源代码地址 yolov5官网还提供的dnn、tensorrt推理链接本人使用的opencv c github代码,代码作者非本人&#xff0c;也是上面作者推荐的…

开始学习vue2基础篇(初体验)

一、什么是VUE&#xff08;官网 &#xff1a;https://cn.vuejs.org/&#xff09; 官方给出的概念 &#xff1a;Vue (读音 /vju ː/ &#xff0c;类似于 view) 是一套用 于构建用户界面的前端框架 渐进式的 JavaScript 框架 二、VUE的特点 易用 &#xff1a;基础只需HTML、CSS、…

4_机械臂运动学基础向量空间

在了解机械臂正解推导的过程中&#xff0c;几个问题一直困扰着我&#xff1a; 1、为什么3*3矩阵可以描述姿态&#xff1f;矩阵更进一步的意义是什么&#xff1f;姿态是否有其他的描述方式&#xff0c;如果有是什么&#xff1f; 2、机械臂法兰中心相对于基座的坐标&#xff0c;6…

PgSQL - 17新特性 - 块级别增量备份

PgSQL - 17新特性 - 块级别增量备份 PgSQL可通过pg_basebackup进行全量备份。在构建复制关系时&#xff0c;创建备机时需要通过pg_basebackup全量拉取一个备份&#xff0c;形成一个mirror。但很多场景下&#xff0c;我们往往不需要进行全量备份/恢复&#xff0c;数据量特别大的…

mysql生成最近24小时整点时间临时表

文章目录 生成最近24小时整点生成最近30天生成12个月 生成最近24小时整点 SELECT-- 每向下推1行, i比上次减去1b.*, i.*,DATE_FORMAT( DATE_SUB( NOW(), INTERVAL ( -( i : i - 1 ) ) HOUR ), %Y-%m-%d %H:00 ) AS time FROM-- 目的是生成12行数据( SELECTa FROM( SELECT 1 A…

day01 深度学习介绍

目录 1.1深度学习介绍 1.2神经网络NN 1、概念&#xff1a; 2、神经元 3、&#xff08;单层&#xff09;神经网络 4、感知机&#xff08;两层&#xff09; 5、多层神经网络 6、激活函数 &#xff08;1&#xff09;饱和与非饱和激活函数 &#xff08;2&#xff09;饱和激活…

基于 IDEA 进行 Maven 工程构建

1. 构建概念和构建过程 项目构建是指将源代码、依赖库和资源文件等转换成可执行或可部署的应用程序的过程&#xff0c;在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤。 项目构建是软件开发过程中至关重要的一部分&#xff0c;它能够大大提高软件开发效率&am…

Redis 面试题 | 05.精选Redis高频面试题

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

PowerShell install 一键部署grafana

grafana 前言 Grafana 是一款开源的数据可视化和监控仪表盘工具。它提供了丰富的数据查询、可视化和报警功能,可用于实时监控、数据分析和故障排除等领域。 通过 Grafana,您可以连接到各种不同的数据源,包括时序数据库(如 Prometheus、InfluxDB)和关系型数据库(如 MySQ…

使用DTS实现TiDB到GaiaDB数据迁移

1 概览 本文主要介绍通过 DTS 数据迁移功能&#xff0c;结合消息服务 for Kafka 与 TiDB 数据库的 Pump、Drainer 组件&#xff0c;完成从TiDB迁移至百度智能云云原生数据库 GaiaDB。 消息服务 for Kafka&#xff1a;详细介绍参见&#xff1a;消息服务 for Kafka 产品介绍百度智…

Elasticsearch:介绍 kNN query,这是进行 kNN 搜索的专家方法

作者&#xff1a;来自 Elastic Mayya Sharipova, Benjamin Trent 当前状况&#xff1a;kNN 搜索作为顶层部分 Elasticsearch 中的 kNN 搜索被组织为搜索请求的顶层&#xff08;top level&#xff09;部分。 我们这样设计是为了&#xff1a; 无论分片数量多少&#xff0c;它总…