Auf dieser Seite

Bluetooth Low Energy-Herzfrequenz-Server

Ein Beispiel, das veranschaulicht, wie ein GATT-Dienst eingerichtet und bekannt gegeben wird. Das Beispiel veranschaulicht die Verwendung der Qt Bluetooth Low-Energy-Klassen im Zusammenhang mit Peripherie- (Slave-)Funktionalität.

Der Bluetooth Low Energy-Herzfrequenzserver ist eine Befehlszeilenanwendung, die zeigt, wie man mithilfe der Qt Bluetooth API. Die Anwendung umfasst das Einrichten eines Dienstes, dessen Bekanntgabe sowie die Benachrichtigung von Clients über Änderungen an Merkmalswerten.

Das Beispiel nutzt die folgenden Qt-Klassen:

Das Beispiel implementiert eine Serveranwendung, d. h., es verfügt über keine grafische Benutzeroberfläche. Um zu veranschaulichen, was die Anwendung tut, können Sie das Beispiel „Heart Rate Game“ verwenden, das im Grunde das clientseitige Gegenstück zu dieser Anwendung darstellt.

Bluetooth-Berechtigung prüfen

Bevor die Anwendung einen Dienst erstellen und mit der Werbung beginnen kann, müssen wir prüfen, ob die Anwendung über die Berechtigung zur Nutzung von Bluetooth verfügt.

auto permissionStatus = app.checkPermission(QBluetoothPermission{});

Bluetooth-Berechtigung anfordern

Wenn der Status der Bluetooth-Berechtigung unklar ist, müssen wir eine Berechtigung zur Nutzung von Bluetooth anfordern.

if (permissionStatus== Qt::PermissionStatus::Undetermined) {
    qInfo("Requesting Bluetooth permission ...");
    app.requestPermission(QBluetoothPermission{}, [&permissionStatus](const QPermission&permission){
        qApp->exit();
        permissionStatus = permission.status();
    });
    // Nun warten, bis die Berechtigungsanfrage abgearbeitet ist.
    app.exec();
}

Einrichten von Werbedaten und Parametern

Zur Konfiguration des Werbeprozesses werden zwei Klassen verwendet:

In unserem Beispiel verwenden wir einfach die Standardparameter.

Die in der „ QLowEnergyAdvertisingData “ enthaltenen Informationen sind für andere Geräte sichtbar, die gerade auf Signalsuche sind. Diese können anhand dieser Informationen entscheiden, ob sie eine Verbindung herstellen möchten oder nicht. In unserem Beispiel geben wir die Art des von uns angebotenen Dienstes, einen Namen, der unser Gerät für Menschen verständlich beschreibt, sowie die Sendeleistung des Geräts an. Letzteres ist für potenzielle Kunden oft hilfreich, da sie anhand eines Vergleichs der empfangenen Signalstärke mit der angekündigten erkennen können, wie weit entfernt sich unser Gerät befindet.

Hinweis: Der Platz für die Broadcast-Daten ist sehr begrenzt (insgesamt nur 31 Byte), daher sollten Daten mit variabler Länge, wie beispielsweise der Gerätename, so kurz wie möglich gehalten werden.

QLowEnergyAdvertisingData advertisingData;
advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral);
advertisingData.setIncludePowerLevel(true);
advertisingData.setLocalName("HeartRateServer");
advertisingData.setServices(QList<QBluetoothUuid>() << QBluetoothUuid::ServiceClassUuid::HeartRate);

Einrichten der Dienstdaten

Als Nächstes konfigurieren wir die Art des Dienstes, den wir anbieten möchten. Wir verwenden den in der Bluetooth-Spezifikation definierten Dienst „ Heart Rate “ in seiner Minimalform, d. h. bestehend ausschließlich aus der Eigenschaft „ Heart Rate Measurement “. Diese Eigenschaft muss die Eigenschaft „ Notify “ (und keine anderen) unterstützen und über einen Deskriptor „ Client Characteristic Configuration “ verfügen, der es Clients ermöglicht, sich zu registrieren, um über Änderungen an Eigenschaftswerten benachrichtigt zu werden. Wir setzen den anfänglichen Herzfrequenzwert auf Null, da er ohnehin nicht ausgelesen werden kann (der Client kann den Wert ausschließlich über Benachrichtigungen abrufen).

QLowEnergyCharacteristicData charData;
charData.setUuid(QBluetoothUuid::CharacteristicType::HeartRateMeasurement);
charData.setValue(QByteArray(2, 0));
charData.setProperties(QLowEnergyCharacteristic::Notify);
const QLowEnergyDescriptorData clientConfig(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration,
                                            QByteArray(2, 0));
charData.addDescriptor(clientConfig);

QLowEnergyServiceData serviceData;
serviceData.setType(QLowEnergyServiceData::ServiceTypePrimary);
serviceData.setUuid(QBluetoothUuid::ServiceClassUuid::HeartRate);
serviceData.addCharacteristic(charData);

Ankündigung und Abhören eingehender Verbindungen

Nachdem nun alle Daten eingerichtet sind, können wir mit dem Advertising beginnen. Zunächst erstellen wir ein ` QLowEnergyController `-Objekt in der ` peripheral role ` und verwenden es, um ein (dynamisches) ` QLowEnergyService `-Objekt aus unserem (statischen) ` QLowEnergyServiceData` zu erstellen. Anschließend rufen wir ` QLowEnergyController::startAdvertising()` auf. Beachten Sie, dass wir unser ` QLowEnergyAdvertisingData ` zweimal übergeben: Das erste Argument dient als eigentliche Anzeigeninformation, das zweite als Scan-Antwortdaten. Sie könnten unterschiedliche Informationen transportieren, aber hier besteht dafür kein Bedarf. Außerdem übergeben wir eine standardmäßig konstruierte Instanz von ` QLowEnergyAdvertisingParameters`, da die Standard-Advertising-Parameter für uns ausreichend sind. Ist ein Client an dem beworbenen Dienst interessiert, kann er nun eine Verbindung zu unserem Gerät herstellen. In diesem Fall beendet das Gerät das Advertising und das Signal ` QLowEnergyController::connected()` wird ausgelöst.

Hinweis: Wenn ein Client die Verbindung trennt, wird die Werbung nicht automatisch fortgesetzt. Wenn Sie dies wünschen, müssen Sie eine Verbindung zum Signal „ QLowEnergyController::disconnected “ () herstellen und im entsprechenden Slot „ QLowEnergyController::startAdvertising “ () aufrufen.

bool errorOccurred = false;
const std::unique_ptr<QLowEnergyController> leController(QLowEnergyController::createPeripheral());
auto errorHandler = [&leController, &errorOccurred](QLowEnergyController::Error errorCode) {
        qWarning().noquote().nospace() << errorCode << " occurred: "
           << leController->errorString();
        if (errorCode != QLowEnergyController::RemoteHostClosedError) {
            qWarning("Heartrate-server quitting due to the error.");
            errorOccurred = true;
            QCoreApplication::quit();
        }
};
QObject::connect(leController.get(), &QLowEnergyController::errorOccurred, errorHandler);

std::unique_ptr<QLowEnergyService> service(leController->addService(serviceData));
leController->startAdvertising(QLowEnergyAdvertisingParameters(), advertisingData,
                               advertisingData);
if (errorOccurred)
    return-1;

Bereitstellung der Herzfrequenz

So weit, so gut. Aber wie gelangt ein Client eigentlich an die Herzfrequenz? Dies geschieht durch regelmäßige Aktualisierung des Werts der entsprechenden Eigenschaft im QLowEnergyService -Objekt, das wir im obigen Codeausschnitt vom QLowEnergyController erhalten haben. Die Quelle der Herzfrequenz wäre normalerweise ein Sensor, aber in unserem Beispiel denken wir uns einfach Werte aus, die wir zwischen 60 und 100 schwanken lassen. Der wichtigste Teil im folgenden Codeausschnitt ist der Aufruf von ` QLowEnergyService::writeCharacteristic`. Wenn ein Client gerade verbunden ist und Benachrichtigungen durch einen Schreibvorgang an den oben genannten ` Client Characteristic Configuration` aktiviert hat, wird er über den neuen Wert benachrichtigt.

QTimer heartbeatTimer;
quint8 currentHeartRate = 60;
enum ValueChange { ValueUp, ValueDown } valueChange = ValueUp;
const auto heartbeatProvider = [&service, &currentHeartRate, &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::CharacteristicType::HeartRateMeasurement);
    Q_ASSERT(characteristic.isValid());
    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);

Beispielprojekt @ code.qt.io

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.