Serveur de fréquence cardiaque Bluetooth Low Energy
Un exemple démontrant comment mettre en place et annoncer un service GATT. L'exemple démontre l'utilisation des classes Qt Bluetooth Low Energy liées à la fonctionnalité périphérique (esclave).
Le serveur de fréquence cardiaque Bluetooth Low Energy est une application en ligne de commande qui montre comment développer un serveur GATT Bluetooth à l'aide de la classe Qt Bluetooth API. L'application couvre la mise en place d'un service, sa publicité et la notification aux clients des changements de valeurs caractéristiques.
L'exemple utilise les classes Qt suivantes :
- QLowEnergyAdvertisingData
- QLowEnergyAdvertisingParameters
- QLowEnergyServiceData
- QLowEnergyCharacteristicData
- QLowEnergyDescriptorData
- QLowEnergyController
- QLowEnergyService
L'exemple met en œuvre une application serveur, ce qui signifie qu'il n'a pas d'interface utilisateur graphique. Pour visualiser ce qu'il fait, vous pouvez utiliser l'exemple Heart Rate Game, qui est en fait la contrepartie côté client de cette application.
Vérification de la permission Bluetooth
Avant que l'application puisse créer un service et commencer à faire de la publicité, nous devons vérifier si l'application a la permission d'utiliser Bluetooth.
auto permissionStatus = app.checkPermission(QBluetoothPermission{});
Demander la permission Bluetooth
Si le statut de l'autorisation Bluetooth est indéterminé, nous devons demander la permission d'utiliser Bluetooth.
if (permissionStatus == Qt::PermissionStatus::Undetermined) { qInfo("Requesting Bluetooth permission ..."); app.requestPermission(QBluetoothPermission{}, [&permissionStatus](const QPermission &permission){ qApp->exit(); permissionStatus = permission.status() ; }) ; // Maintenant, attendez que la demande de permission soit résolue.app.exec() ; }
Configuration des données et des paramètres publicitaires
Deux classes sont utilisées pour configurer le processus de publicité :
- QLowEnergyAdvertisingData spécifie les informations à diffuser
- QLowEnergyAdvertisingParameters est utilisée pour des aspects spécifiques tels que le réglage de l'intervalle de publicité ou le contrôle des appareils autorisés à se connecter.
Dans notre exemple, nous utilisons simplement les paramètres par défaut.
Les informations contenues dans le site QLowEnergyAdvertisingData seront visibles par les autres appareils en cours de balayage. Ils peuvent les utiliser pour décider s'ils veulent établir une connexion ou non. Dans notre exemple, nous incluons le type de service que nous offrons, un nom qui décrit correctement notre appareil aux humains et le niveau de puissance d'émission de l'appareil. Ce dernier point est souvent utile aux clients potentiels, car ils peuvent savoir à quelle distance se trouve notre appareil en comparant la puissance du signal reçu à celle annoncée.
Remarque : l'espace pour les données publicitaires est très limité (seulement 31 octets au total), c'est pourquoi les données de longueur variable telles que le nom de l'appareil doivent être aussi courtes que possible.
QLowEnergyAdvertisingData advertisingData; advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral); advertisingData.setIncludePowerLevel(true); advertisingData.setLocalName("HeartRateServer"); advertisingData.setServices(QList<QBluetoothUuid>() << QBluetoothUuid::ServiceClassUuid::HeartRate);
Configuration des données de service
Ensuite, nous configurons le type de service que nous voulons offrir. Nous utilisons le service Heart Rate tel qu'il est défini dans la spécification Bluetooth sous sa forme minimale, c'est-à-dire qu'il se compose uniquement de la caractéristique Heart Rate Measurement. Cette caractéristique doit prendre en charge la propriété Notify (et aucune autre) et doit avoir un descripteur Client Characteristic Configuration, qui permet aux clients de s'enregistrer pour être informés des modifications apportées aux valeurs de la caractéristique. La valeur initiale de la fréquence cardiaque est fixée à zéro, car elle ne peut de toute façon pas être lue (la seule façon dont le client peut obtenir la valeur est par le biais de notifications).
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);
Publicité et écoute des connexions entrantes
Maintenant que toutes les données ont été configurées, nous pouvons commencer à faire de la publicité. Tout d'abord, nous créons un objet QLowEnergyController dans peripheral role et l'utilisons pour créer un objet (dynamique) QLowEnergyService à partir de notre objet (statique) QLowEnergyServiceData. Nous appelons ensuite QLowEnergyController::startAdvertising(). Notez que nous transmettons notre QLowEnergyAdvertisingData deux fois : le premier argument sert de données publicitaires proprement dites, le second de données de réponse au balayage. Ils pourraient transporter des informations différentes, mais ici nous n'en avons pas besoin. Nous passons également une instance de QLowEnergyAdvertisingParameters construite par défaut, car les paramètres publicitaires par défaut nous conviennent. Si un client est intéressé par le service annoncé, il peut maintenant établir une connexion avec notre appareil. Lorsque cela se produit, l'appareil arrête la publicité et le signal QLowEnergyController::connected() est émis.
Remarque : lorsqu'un client se déconnecte, la publicité ne reprend pas automatiquement. Si vous voulez que cela se produise, vous devez vous connecter au signal QLowEnergyController::disconnected() et appeler QLowEnergyController::startAdvertising() dans le slot correspondant.
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;
Fournir la fréquence cardiaque
Jusqu'ici, tout va bien. Mais comment un client peut-il obtenir la fréquence cardiaque ? En mettant régulièrement à jour la valeur de la caractéristique correspondante dans l'objet QLowEnergyService que nous avons reçu de QLowEnergyController dans l'extrait de code ci-dessus. La source de la fréquence cardiaque serait normalement une sorte de capteur, mais dans notre exemple, nous inventons simplement des valeurs que nous laissons osciller entre 60 et 100. La partie la plus importante de l'extrait de code suivant est l'appel à QLowEnergyService::writeCharacteristic. Si un client est actuellement connecté et a activé les notifications en écrivant à l'objet Client Characteristic Configuration, il sera informé de la nouvelle valeur.
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::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);
© 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.