Qt 5.7 QBluetooth LE GATT 服务器示例 Raspberry Pi 3 和 BlueZ 5.39
Qt 5.7 QBluetooth LE GATT Server Example with Raspberry Pi 3 and BlueZ 5.39
我正在尝试 运行 Qt 5.7 beta QBluetooth GATT 服务器示例 ( https://doc-snapshots.qt.io/qt5-dev/qtbluetooth-heartrate-server-example.html ) 在 Raspberry Pi 3 上集成 Broadcom 蓝牙芯片。
蓝牙在我的 Pi 3 上运行良好,hci0 接口在重新启动后 "UP RUNNING":
root@raspberrypi:~/bluez-5.39# hciconfig -a
hci0: Type: BR/EDR Bus: UART
BD Address: B8:27:EB:6F:71:A7 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING PSCAN
RX bytes:2316 acl:0 sco:0 events:99 errors:0
TX bytes:2676 acl:0 sco:0 commands:99 errors:0
Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH SNIFF
Link mode: SLAVE ACCEPT
Name: 'raspberrypi'
Class: 0x000000
Service Classes: Unspecified
Device Class: Miscellaneous,
HCI Version: 4.1 (0x7) Revision: 0xb6
LMP Version: 4.1 (0x7) Subversion: 0x2209
Manufacturer: Broadcom Corporation (15)
我成功下载、编译并安装了最新的 BlueZ 5.39,它包含了 BlueZ BLE 功能的完整 DBus 接口:
http://www.kernel.org/pub/linux/bluetooth/bluez-5.39.tar.xz
我已经确认在路径中选择的版本是正确的版本:
[bluetooth]# version
Version 5.39
我使用 buildroot 交叉编译 Qt 5.7 并将其库部署到 Pi。我可以在我的主机上成功构建并 运行 在 Pi 上生成可执行文件。
Qt 的 GATT 示例非常简单,我只添加了 2 "qDebug" 行来查看一些控制台输出。为了完整起见,我将其粘贴在这里:
#include <QtBluetooth/qlowenergyadvertisingdata.h>
#include <QtBluetooth/qlowenergyadvertisingparameters.h>
#include <QtBluetooth/qlowenergycharacteristic.h>
#include <QtBluetooth/qlowenergycharacteristicdata.h>
#include <QtBluetooth/qlowenergydescriptordata.h>
#include <QtBluetooth/qlowenergycontroller.h>
#include <QtBluetooth/qlowenergyservice.h>
#include <QtBluetooth/qlowenergyservicedata.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qlist.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qtimer.h>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QLowEnergyAdvertisingData advertisingData;
advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral);
advertisingData.setIncludePowerLevel(true);
advertisingData.setLocalName("BlueZ 5 GATT Server");
advertisingData.setServices(QList<QBluetoothUuid>() << QBluetoothUuid::HeartRate);
QLowEnergyCharacteristicData charData;
charData.setUuid(QBluetoothUuid::HeartRateMeasurement);
charData.setValue(QByteArray(2, 0));
charData.setProperties(QLowEnergyCharacteristic::Notify);
const QLowEnergyDescriptorData clientConfig(QBluetoothUuid::ClientCharacteristicConfiguration,
QByteArray(2, 0));
charData.addDescriptor(clientConfig);
QLowEnergyServiceData serviceData;
serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
serviceData.setUuid(QBluetoothUuid::HeartRate);
serviceData.addCharacteristic(charData);
const QScopedPointer<QLowEnergyController> leController(QLowEnergyController::createPeripheral());
const QScopedPointer<QLowEnergyService> service(leController->addService(serviceData));
qDebug() << "Beginning to advertise...";
leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,
advertisingData);
QTimer heartbeatTimer;
quint8 currentHeartRate = 60;
enum ValueChange { ValueUp, ValueDown } valueChange = ValueUp;
const auto heartbeatProvider = [&service, ¤tHeartRate, &valueChange]() {
QByteArray value;
value.append(char(0)); // Flags that specify the format of the value.
value.append(char(currentHeartRate)); // Actual value.
QLowEnergyCharacteristic characteristic
= service->characteristic(QBluetoothUuid::HeartRateMeasurement);
Q_ASSERT(characteristic.isValid());
qDebug() << "Changing characteristic to: " << value;
service->writeCharacteristic(characteristic, value); // Potentially causes notification.
if (currentHeartRate == 60)
valueChange = ValueUp;
else if (currentHeartRate == 100)
valueChange = ValueDown;
if (valueChange == ValueUp)
++currentHeartRate;
else
--currentHeartRate;
};
QObject::connect(&heartbeatTimer, &QTimer::timeout, heartbeatProvider);
heartbeatTimer.start(1000);
auto reconnect = [&leController, advertisingData]() {
leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,
advertisingData);
};
QObject::connect(leController.data(), &QLowEnergyController::disconnected, reconnect);
return app.exec();
}
专业文件:
TEMPLATE = app
TARGET = qt-gatt
QT += bluetooth
CONFIG += c++11
SOURCES += main.cpp
## Install directory
target.path = /home/pi
INSTALLS += target
当我 运行 Pi 上的应用程序在全新启动后以 root 身份运行时 - 它 运行s 并输出我的打印消息:
root@raspberrypi:/home/pi# ./qt-gatt
Beginning to advertise...
Changing characteristic to: "\x00<"
Changing characteristic to: "\x00="
Changing characteristic to: "\x00>"
Changing characteristic to: "\x00?"
没有显示任何错误或警告 - 但我的 none 台设备可以看到它。我的 iPhone 和 Mac 可以看到其他 BLE 设备,但不能看到 Pi。代码将 Pi 设置为 "discoverable"。
我怎样才能完成这项工作/我做错了什么?
您可能已经知道这一点,但我认为 bluetoothd 仍然需要使用 -E 启动实验模式。
您还可以在 main()
的顶部添加以下行以查看来自 QBluetooth
的日志记录。让我们知道您看到或弄清楚了什么。我正在尝试做一件非常相似的事情,现在很幸运……日志记录似乎在我的平台上不起作用。
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
我正在尝试 运行 Qt 5.7 beta QBluetooth GATT 服务器示例 ( https://doc-snapshots.qt.io/qt5-dev/qtbluetooth-heartrate-server-example.html ) 在 Raspberry Pi 3 上集成 Broadcom 蓝牙芯片。
蓝牙在我的 Pi 3 上运行良好,hci0 接口在重新启动后 "UP RUNNING":
root@raspberrypi:~/bluez-5.39# hciconfig -a
hci0: Type: BR/EDR Bus: UART
BD Address: B8:27:EB:6F:71:A7 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING PSCAN
RX bytes:2316 acl:0 sco:0 events:99 errors:0
TX bytes:2676 acl:0 sco:0 commands:99 errors:0
Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH SNIFF
Link mode: SLAVE ACCEPT
Name: 'raspberrypi'
Class: 0x000000
Service Classes: Unspecified
Device Class: Miscellaneous,
HCI Version: 4.1 (0x7) Revision: 0xb6
LMP Version: 4.1 (0x7) Subversion: 0x2209
Manufacturer: Broadcom Corporation (15)
我成功下载、编译并安装了最新的 BlueZ 5.39,它包含了 BlueZ BLE 功能的完整 DBus 接口:
http://www.kernel.org/pub/linux/bluetooth/bluez-5.39.tar.xz
我已经确认在路径中选择的版本是正确的版本:
[bluetooth]# version
Version 5.39
我使用 buildroot 交叉编译 Qt 5.7 并将其库部署到 Pi。我可以在我的主机上成功构建并 运行 在 Pi 上生成可执行文件。
Qt 的 GATT 示例非常简单,我只添加了 2 "qDebug" 行来查看一些控制台输出。为了完整起见,我将其粘贴在这里:
#include <QtBluetooth/qlowenergyadvertisingdata.h>
#include <QtBluetooth/qlowenergyadvertisingparameters.h>
#include <QtBluetooth/qlowenergycharacteristic.h>
#include <QtBluetooth/qlowenergycharacteristicdata.h>
#include <QtBluetooth/qlowenergydescriptordata.h>
#include <QtBluetooth/qlowenergycontroller.h>
#include <QtBluetooth/qlowenergyservice.h>
#include <QtBluetooth/qlowenergyservicedata.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qlist.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qtimer.h>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QLowEnergyAdvertisingData advertisingData;
advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral);
advertisingData.setIncludePowerLevel(true);
advertisingData.setLocalName("BlueZ 5 GATT Server");
advertisingData.setServices(QList<QBluetoothUuid>() << QBluetoothUuid::HeartRate);
QLowEnergyCharacteristicData charData;
charData.setUuid(QBluetoothUuid::HeartRateMeasurement);
charData.setValue(QByteArray(2, 0));
charData.setProperties(QLowEnergyCharacteristic::Notify);
const QLowEnergyDescriptorData clientConfig(QBluetoothUuid::ClientCharacteristicConfiguration,
QByteArray(2, 0));
charData.addDescriptor(clientConfig);
QLowEnergyServiceData serviceData;
serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
serviceData.setUuid(QBluetoothUuid::HeartRate);
serviceData.addCharacteristic(charData);
const QScopedPointer<QLowEnergyController> leController(QLowEnergyController::createPeripheral());
const QScopedPointer<QLowEnergyService> service(leController->addService(serviceData));
qDebug() << "Beginning to advertise...";
leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,
advertisingData);
QTimer heartbeatTimer;
quint8 currentHeartRate = 60;
enum ValueChange { ValueUp, ValueDown } valueChange = ValueUp;
const auto heartbeatProvider = [&service, ¤tHeartRate, &valueChange]() {
QByteArray value;
value.append(char(0)); // Flags that specify the format of the value.
value.append(char(currentHeartRate)); // Actual value.
QLowEnergyCharacteristic characteristic
= service->characteristic(QBluetoothUuid::HeartRateMeasurement);
Q_ASSERT(characteristic.isValid());
qDebug() << "Changing characteristic to: " << value;
service->writeCharacteristic(characteristic, value); // Potentially causes notification.
if (currentHeartRate == 60)
valueChange = ValueUp;
else if (currentHeartRate == 100)
valueChange = ValueDown;
if (valueChange == ValueUp)
++currentHeartRate;
else
--currentHeartRate;
};
QObject::connect(&heartbeatTimer, &QTimer::timeout, heartbeatProvider);
heartbeatTimer.start(1000);
auto reconnect = [&leController, advertisingData]() {
leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,
advertisingData);
};
QObject::connect(leController.data(), &QLowEnergyController::disconnected, reconnect);
return app.exec();
}
专业文件:
TEMPLATE = app
TARGET = qt-gatt
QT += bluetooth
CONFIG += c++11
SOURCES += main.cpp
## Install directory
target.path = /home/pi
INSTALLS += target
当我 运行 Pi 上的应用程序在全新启动后以 root 身份运行时 - 它 运行s 并输出我的打印消息:
root@raspberrypi:/home/pi# ./qt-gatt
Beginning to advertise...
Changing characteristic to: "\x00<"
Changing characteristic to: "\x00="
Changing characteristic to: "\x00>"
Changing characteristic to: "\x00?"
没有显示任何错误或警告 - 但我的 none 台设备可以看到它。我的 iPhone 和 Mac 可以看到其他 BLE 设备,但不能看到 Pi。代码将 Pi 设置为 "discoverable"。
我怎样才能完成这项工作/我做错了什么?
您可能已经知道这一点,但我认为 bluetoothd 仍然需要使用 -E 启动实验模式。
您还可以在 main()
的顶部添加以下行以查看来自 QBluetooth
的日志记录。让我们知道您看到或弄清楚了什么。我正在尝试做一件非常相似的事情,现在很幸运……日志记录似乎在我的平台上不起作用。
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));