1.要使用qt藍牙模塊, 項目的 .pro要聲明使用
2.有了lambda函數后,不用再一個個聲明和創建具名槽函數的感覺挺好,就是代碼成一坨了
3.雖然說是低功耗藍牙,但還是要記得用完后斷開和外設店連接,之前忘記斷開,一晚上一個紐扣電池的點就被耗光了
4.GATT Profile 簡介
- 搜尋附近全部的藍牙設備
- 根據搜尋出的藍牙設備信息,篩選出要連接的藍牙設備進行連接
- 建立連接后,去獲取該藍牙設備等services列表,根據約定好的服務uuid篩選出自己需要的服務
- 發現對應的服務后,根據約定好的服務下characteristic特性id,創建特征對象,並監聽特征對象內容的變化
- 向客戶端特征配置對象寫入特征生效消息,開始接收外圍藍牙設備。
bluedevice.h:
1 #ifndef BLUEDEVICE_H 2 #define BLUEDEVICE_H
3 #include <QObject>
4 #include<QBluetoothDeviceDiscoveryAgent>
5 #include<QBluetoothDeviceInfo>
6 #include<QBluetoothUuid>
7 #include<QBluetoothServiceInfo>
8 #include<QLowEnergyController>
9 #include<QLowEnergyService>
10 #include<QLowEnergyDescriptor>
11 class BlueDevice: public QObject{ 12 Q_OBJECT 13 public: 14
15 BlueDevice(); 16 QString getAddress(QBluetoothDeviceInfo device) const; 17 private: 18 QList<QBluetoothDeviceInfo> device_list; //存放搜索到到藍牙設備列表
19 QBluetoothDeviceDiscoveryAgent *m_deviceDiscoveryAgent; //設備搜索對象
20 QLowEnergyController *m_controler; //單個藍牙設備控制器
21 QLowEnergyService *m_service; //服務對象實例
22 }; 23
24 #endif // BLUEDEVICE_H
bluedevice.cpp:
1 #include "bluedevice.h"
2 #include <QDebug>
3 #include<QTimer>
4
5 BlueDevice::BlueDevice() { 6 qDebug() << "enter bludedevice constructor...."; 7
8 m_deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this); 9 m_deviceDiscoveryAgent->setLowEnergyDiscoveryTimeout(5000); 10
11 //每次發現新設備時觸發
12 connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this ,[this]() { 13 qDebug() << "find a new bluebooth device"; 14 }); 15
16 //藍牙設備搜索完成后,篩選出目標設備進行連接,並進行相關信號與槽函數的綁定
17 connect(m_deviceDiscoveryAgent,&QBluetoothDeviceDiscoveryAgent::finished, this, [this]() { 18 device_list = this->m_deviceDiscoveryAgent->discoveredDevices(); 19
20 //遍歷顯示設備詳情
21 QList<QBluetoothDeviceInfo>::iterator it; 22 for(it=device_list.begin(); it != device_list.end(); it++) { 23
24 // 外圍藍牙設備對象
25 QBluetoothDeviceInfo tmp_device = *it; 26 QString device_name = tmp_device.name(); 27 //qDebug() <<"device name:::" << device_name; 28 //qDebug() << "device address:::" << this->getAddress(tmp_device); 29
30 //打印搜索出來的全部低功耗藍牙
31 if (tmp_device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) { 32 qDebug() << " low Energy device ...."; 33 qDebug() <<"22222device name:::" << device_name; 34 } 35
36 //正則匹配目標設備,
37 QString pattern_str = "^Eric.*"; //qt中正則匹配任意個字符,需要使用.*而不是*
38 QRegExp rx(pattern_str); 39 if(!rx.exactMatch(device_name)) { 40 continue; 41 } 42 qDebug() <<"device name:::" << device_name; 43 qDebug() << "device address:::" << this->getAddress(tmp_device); 44
45 // 創建藍牙設備控制器對象
46 m_controler = new QLowEnergyController(tmp_device, this); 47
48 // 監聽目標設備連接成功消息,連接成功后,搜索目標設備等服務列表
49 connect(m_controler, &QLowEnergyController::connected, this, [this](){ 50 qDebug() << "m_controler connected ......"; 51 //必須要在連接建立后 執行開始尋找service的函數 52 //之前調試,就是因為沒有在設備連接后主動請求獲取服務列表信息,后續監聽便沒有觸發
53 m_controler->discoverServices(); 54 }); 55
56 // 監聽發現服務消息,如果服務的uuid 為約定好的要使用服務類型,則進行后續處理
57 connect(m_controler,&QLowEnergyController::serviceDiscovered, this, [this](QBluetoothUuid serviceUuid) { 58 if(serviceUuid == QBluetoothUuid( quint16(0xffd0))) { //我們用的服務類型是0xffd0對應的uuid 59
60 //發現匹配的服務后,使用控制器對象創建服務對象
61 m_service = m_controler->createServiceObject(serviceUuid,this); 62 if(m_service) { 63
64 // 服務對象創建成功后,堅挺服務狀態變化,如果狀態變成已發現,則進行后續服務下特征對象獲取
65 connect(m_service,&QLowEnergyService::stateChanged, this, [this]() { 66 qDebug() << "service state change" << m_service->state() << ",||||||"; 67
68 //發現服務, 建立characteristic對象實例
69 if(m_service->state() == QLowEnergyService::ServiceDiscovered) { 70 QLowEnergyCharacteristic hrChar = m_service->characteristic(QBluetoothUuid(quint16(0xfff6))); 71 if(!hrChar.isValid()) { 72 qDebug() << "characteristic fff6 error:::"; 73 } 74 // 設置特征對象可用 75 //enable the chracteristic notification by write 0x01 to client characteristic configuration
76 QLowEnergyDescriptor m_notificationDesc = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration); 77 if (m_notificationDesc.isValid()) { 78 if(hrChar.properties() & QLowEnergyCharacteristic::Notify) { 79 qDebug() << ""; 80 } 81 m_service->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0100")); 82 } 83 } 84 }); 85
86 // 通過監聽特征對象的變化,不斷獲得鞋墊壓力數據。
87 connect(m_service,&QLowEnergyService::characteristicChanged, this, 88 [this](QLowEnergyCharacteristic c,QByteArray value) { 89 qDebug() << "characteristicChanged state change::" <<c.uuid()<< ",||||||"; 90 qDebug() << "value length::" << value.length(); 91 qDebug() << "value length::" << value; 92
93 QByteArray sub_1 = value.mid(0,2); 94 QByteArray sub_2 = value.mid(2,2); 95 QByteArray sub_3 = value.mid(4,2); 96
97 bool ok; 98 // num 1,2,3 分別對應三個壓力感應點的壓力值
99 int num_1 = QString(sub_1.toHex()).toInt(&ok,16); 100 qDebug() << "num_1:::" << num_1; 101 int num_2 = QString(sub_2.toHex()).toInt(&ok,16); 102 qDebug() << "num_1:::" << num_2; 103 int num_3 = QString(sub_3.toHex()).toInt(&ok,16); 104 qDebug() << "num_1:::" << num_3; 105
106 } 107 ); 108
109 // 觸發服務詳情發現函數 ,不要忘記調用
110 m_service->discoverDetails(); 111 } 112 } 113 }); 114
115 connect(m_controler,&QLowEnergyController::discoveryFinished, this, [this]() { 116 qDebug() << "finish service discovery"; 117 }); 118
119 //連接外圍設備
120 m_controler->connectToDevice(); 121
122 //QTimer *timer = new QTimer(this); 123 //connect(timer, &QTimer::timeout, this, [this](){ qDebug() <<"state:::" << this->m_controler->state();}); 124 //timer->start(1000);
125 } 126 }); 127
128 // 開始外圍設備搜索
129 m_deviceDiscoveryAgent->start(); 130
131 } 132
133 // mac和其他系統上address獲取有少許差異,參見官方文檔
134 QString BlueDevice::getAddress(QBluetoothDeviceInfo device) const
135 { 136 #ifdef Q_OS_MAC 137 // On OS X and iOS we do not have addresses, 138 // only unique UUIDs generated by Core Bluetooth.
139 return device.deviceUuid().toString(); 140 #else
141 return device.address().toString(); 142 #endif
143 } 144
145 //void BlueDevice::getNewService(QBluetoothServiceInfo info) { 146 // qDebug() << "ppppp uuuuuuuuuu"; 147 //}