二十五、QT的BLE蓝牙操作,连接ECB02蓝牙模块收发信息

发布时间 2023-09-17 14:31:23作者: 稚终KINO

1.注意事项

(1)pro文件中引入bluetooth模块

(2)安卓端运行时,需要同时打开蓝牙和定位才能获取到附近的蓝牙设备

(3)mingw套件不能在Windows上运行,需要使用MSVC套件编译才能在Windows上运行

2.操作步骤

(1)使用QBluetoothLocalDevice类对设备蓝牙进行操作,判断设备蓝牙是否开启,开启和关闭设备蓝牙,hostMode方法判断蓝牙设备打开状态,powerOn方法打开蓝牙设备,setHostMode方法关闭蓝牙设备

(2)使用QBluetoothDeviceDiscoveryAgent类对附近可用设备进行扫描,setLowEnergyDiscoveryTimeout方法设置扫描超时时间,设置为0的话会一直进行扫描,为deviceDiscovered信号绑定槽,每发现一台可用设备便会触发此信号,携带参数QBluetoothDeviceInfo,每台设备的信息,调用start方法开始扫描蓝牙设备,参数为指定的蓝牙设备类型

(3)使用QLowEnergyController类的静态方法createCentral创建蓝牙控制器对象,参数为QBluetoothDeviceInfo对象,为serviceDiscovered信号绑定槽,携带参数为QBluetoothUuid,每发现一个服务便会触发此信号,为connected信号绑定槽,用来判断是否正常连接设备,调用connectToDevice方法来连接BLE蓝牙设备,调用disconnectFromDevice方法来断开连接

(4)成功连接到设备以后调用discoverServices方法来获取设备下可用的服务,使用createServiceObject方法来创建蓝牙服务对象,参数为服务UUID

(5)为蓝牙服务对象stateChanged信号绑定槽,监听服务状态变化,状态变化以后向服务写描述符,建立通信,为characteristicChanged信号绑定槽,当有数据传来,此信号被触发,为descriptorWritten信号绑定槽,判断描述符是否成功写入,然后调用discoverDetails方法来获取服务详情,使用writeCharacteristic方法发送数据

(6)服务状态改变后使用characteristics方法获取服务下的所有特征列表,遍历特征对象向特征对象写入描述符,使用isValid方法判断特征和描述符对象是否有效,使用特征对象的descriptor方法由客户端配置创建描述符对象,然后使用服务对象的writeDescriptor方法向设备写入描述符0x0100,建立连接后才能正常接收到数据

3.参考代码

 1 #ifndef MWIDGET_H
 2 #define MWIDGET_H
 3 
 4 #include <QWidget>
 5 #include <QBluetoothDeviceDiscoveryAgent> //蓝牙设备搜索对象
 6 #include <QBluetoothLocalDevice> //本机蓝牙操作
 7 #include <QBluetoothDeviceInfo>
 8 #include <QList>
 9 #include <QListWidgetItem>
10 #include <QLowEnergyController> //蓝牙控制器对象
11 #include <QBluetoothUuid>
12 #include <QLowEnergyService>
13 #include <QLowEnergyCharacteristic>
14 #include <QByteArray>
15 
16 //static const QLatin1String serviceUUID("0000FFF0-0000-1000-8000-00805F9B34FB");
17 //static const QLatin1String readUUID("0000FFF1-0000-1000-8000-00805F9B34FB");
18 //static const QLatin1String writeUUID("0000FFF2-0000-1000-8000-00805F9B34FB");
19 
20 QT_BEGIN_NAMESPACE
21 namespace Ui { class MWidget; }
22 QT_END_NAMESPACE
23 
24 class MWidget : public QWidget
25 {
26     Q_OBJECT
27 
28 public:
29     MWidget(QWidget *parent = nullptr);
30     ~MWidget();
31 
32 private:
33     Ui::MWidget *ui;
34     QBluetoothDeviceDiscoveryAgent *deviceDiscoveryAgent;
35     QBluetoothLocalDevice *localDevice;
36     QList<QBluetoothDeviceInfo> *deviceInfoList;
37     QList<QBluetoothUuid> uuidList;
38     QLowEnergyController *control;
39     QLowEnergyService *mService;
40     QLowEnergyCharacteristic mCharacter;
41     QList<QLowEnergyCharacteristic> charList;
42 
43 private slots:
44     void mDeviceDiscovered(QBluetoothDeviceInfo deviceInfo);
45     void on_openLocalDeviceBtn_clicked();
46     void on_closeLocalDeviceBtn_clicked();
47     void on_searchBtn_clicked();
48     void on_listWidget_itemDoubleClicked(QListWidgetItem *item);
49     void mServiceDiscovered(QBluetoothUuid serviceUuid);
50     void mConnected();
51     void on_uuidListWidget_itemDoubleClicked(QListWidgetItem *item);
52     void mStateChanged(QLowEnergyService::ServiceState newState);
53     void mCharacteristicChanged(QLowEnergyCharacteristic characteristic,QByteArray newValue);
54     void mDescriptorWritten(QLowEnergyDescriptor descriptor,QByteArray newValue);
55     void on_pushButton_clicked();
56 };
57 #endif // MWIDGET_H
  1 #include "mwidget.h"
  2 #include "ui_mwidget.h"
  3 #include <QTextCodec>
  4 
  5 MWidget::MWidget(QWidget *parent)
  6     : QWidget(parent)
  7     , ui(new Ui::MWidget)
  8 {
  9     ui->setupUi(this);
 10     this->setLayout(ui->verticalLayout_2);
 11 
 12     //创建对象
 13     deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
 14     localDevice = new QBluetoothLocalDevice(this);
 15     deviceInfoList = new QList<QBluetoothDeviceInfo>();
 16 
 17     deviceDiscoveryAgent->setLowEnergyDiscoveryTimeout(5000);
 18 
 19     //连接槽
 20     connect(deviceDiscoveryAgent,SIGNAL(deviceDiscovered(QBluetoothDeviceInfo))
 21             ,this,SLOT(mDeviceDiscovered(QBluetoothDeviceInfo)));
 22 }
 23 
 24 MWidget::~MWidget()
 25 {
 26     delete ui;
 27 }
 28 
 29 //蓝牙设备发现槽
 30 void MWidget::mDeviceDiscovered(QBluetoothDeviceInfo deviceInfo)
 31 {
 32     //如果名称不为空切为低功耗蓝牙
 33     if(deviceInfo.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration){
 34         QString label = QString("%1 %2").arg(deviceInfo.name()).arg(deviceInfo.address().toString());
 35         ui->listWidget->addItem(label);
 36         deviceInfoList->append(deviceInfo);
 37     }
 38 }
 39 
 40 //打开本地蓝牙
 41 void MWidget::on_openLocalDeviceBtn_clicked()
 42 {
 43     if(localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff){
 44         localDevice->powerOn();
 45     }
 46 }
 47 
 48 //关闭本地蓝牙
 49 void MWidget::on_closeLocalDeviceBtn_clicked()
 50 {
 51     localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
 52 }
 53 
 54 void MWidget::on_searchBtn_clicked()
 55 {
 56     ui->listWidget->clear();
 57     deviceInfoList->clear();
 58     deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
 59 }
 60 
 61 //双击连接设备
 62 void MWidget::on_listWidget_itemDoubleClicked(QListWidgetItem *item)
 63 {
 64     Q_UNUSED(item);
 65     uuidList.clear();
 66     //创建蓝牙控制器对象
 67     control = QLowEnergyController::createCentral(deviceInfoList->at(ui->listWidget->currentRow()));
 68     connect(control,SIGNAL(serviceDiscovered(QBluetoothUuid))
 69             ,this,SLOT(mServiceDiscovered(QBluetoothUuid)));
 70     connect(control,SIGNAL(connected())
 71             ,this,SLOT(mConnected()));
 72     control->connectToDevice();
 73 }
 74 
 75 //发现服务uuid
 76 void MWidget::mServiceDiscovered(QBluetoothUuid serviceUuid)
 77 {
 78     QString label = QString("%1").arg(serviceUuid.toString());
 79     ui->uuidListWidget->addItem(label);
 80     uuidList.append(serviceUuid);
 81 }
 82 
 83 成功连接到设备
 84 void MWidget::mConnected()
 85 {
 86     ui->textBrowser->append("成功连接"+deviceInfoList->at(ui->listWidget->currentRow()).name());
 87     //搜索服务
 88     uuidList.clear();
 89     control->discoverServices();
 90 }
 91 
 92 双击创建服务UUID,写描述符,建立通讯
 93 void MWidget::on_uuidListWidget_itemDoubleClicked(QListWidgetItem *item)
 94 {
 95     Q_UNUSED(item);
 96     //创建服务
 97     mService = control->createServiceObject(uuidList.at(ui->uuidListWidget->currentRow()),this);
 98     if(mService == NULL){
 99         ui->textBrowser->append("创建服务失败");
100     }else{
101         ui->textBrowser->append("服务创建成功");
102         ui->comboBox->clear();
103         //监听服务状态变化
104         connect(mService,SIGNAL(stateChanged(QLowEnergyService::ServiceState))
105                 ,this,SLOT(mStateChanged(QLowEnergyService::ServiceState)));
106         //服务的characteristic变化,有数据传来
107         connect(mService,SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray))
108                 ,this,SLOT(mCharacteristicChanged(QLowEnergyCharacteristic,QByteArray)));
109         //描述符成功被写
110         connect(mService,SIGNAL(descriptorWritten(QLowEnergyDescriptor,QByteArray))
111                 ,this,SLOT(mDescriptorWritten(QLowEnergyDescriptor,QByteArray)));
112         //服务详情发现函数
113         mService->discoverDetails();
114     }
115 }
116 
117 //服务状态改变
118 void MWidget::mStateChanged(QLowEnergyService::ServiceState newState)
119 {
120     Q_UNUSED(newState);
121     //发现服务
122     if(mService->state() == QLowEnergyService::ServiceDiscovered){
123         charList = mService->characteristics();
124         for(int i=0;i<charList.size();i++){
125             mCharacter = charList.at(i);
126             if(mCharacter.isValid()){
127                 ui->comboBox->addItem(mCharacter.uuid().toString());
128                 QLowEnergyDescriptor descriptor = mCharacter.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);
129                 if(descriptor.isValid()){
130                     mService->writeDescriptor(descriptor,QByteArray::fromHex("0100"));
131                 }
132             }
133         }
134     }
135 }
136 
137 //characteristic变化,数据传来
138 void MWidget::mCharacteristicChanged(QLowEnergyCharacteristic characteristic, QByteArray newValue)
139 {
140     ui->textBrowser->append("接收值成功");
141     Q_UNUSED(characteristic);
142     QTextCodec *code = QTextCodec::codecForName("GBK");
143     QString str = code->toUnicode(newValue);
144     ui->textBrowser->append(str.toUtf8());
145 }
146 
147 //描述符成功被写
148 void MWidget::mDescriptorWritten(QLowEnergyDescriptor descriptor, QByteArray newValue)
149 {
150     ui->textBrowser->append(descriptor.uuid().toString()+":"+newValue);
151     ui->textBrowser->append("描述符写入成功");
152 }
153 
154 void MWidget::on_pushButton_clicked()
155 {
156     QString text = ui->lineEdit->text();
157     QTextCodec *code = QTextCodec::codecForName("GBK");
158     QString str = code->toUnicode(text.toUtf8());
159     mService->writeCharacteristic(charList.at(0),str.toUtf8());
160 }

4.界面效果(手机APP版)

连接设备效果

创建服务,写描述符效果