二十五、QT的BLE蓝牙操作,连接ECB02蓝牙模块收发信息
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版)
连接设备效果
创建服务,写描述符效果