Serveur de fréquence cardiaque Bluetooth Low Energy
Un exemple illustrant comment configurer et diffuser un service GATT. Cet exemple montre l'utilisation des Qt Bluetooth classes Low Energy liées aux fonctionnalités des périphériques (esclaves).
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 Qt Bluetooth API. L’application couvre la configuration d’un service, sa diffusion et la notification aux clients des modifications apportées aux valeurs des caractéristiques.
L'exemple utilise les classes Qt suivantes :
- QLowEnergyAdvertisingData
- QLowEnergyAdvertisingParameters
- QLowEnergyServiceData
- QLowEnergyCharacteristicData
- QLowEnergyDescriptorData
- QLowEnergyController
- QLowEnergyService
Cet exemple implémente une application serveur, ce qui signifie qu’elle ne dispose pas d’interface utilisateur graphique. Pour visualiser son fonctionnement, vous pouvez utiliser l’exemple « Heart Rate Game », qui est en quelque sorte le pendant côté client de cette application.
Vérification de l'autorisation Bluetooth
Avant que l'application puisse créer un service et commencer à diffuser des annonces, nous devons vérifier si elle dispose d'une autorisation pour utiliser le Bluetooth.
auto permissionStatus = app.checkPermission(QBluetoothPermission{});Demander l'autorisation Bluetooth
Si le statut d'autorisation Bluetooth est indéterminé, nous devons demander l'autorisation d'utiliser le Bluetooth.
if (permissionStatus== Qt::PermissionStatus::Undetermined) {
qInfo("Requesting Bluetooth permission ...");
app.requestPermission(QBluetoothPermission{}, [&permissionStatus](const QPermission&permission){
qApp->exit();
permissionStatus = permission.status();
});
// Attendre maintenant que la demande d'autorisation soit traitée.
app.exec();
}Configuration des données et des paramètres publicitaires
Deux classes sont utilisées pour configurer le processus publicitaire :
- QLowEnergyAdvertisingData spécifie les informations à diffuser
- QLowEnergyAdvertisingParameters sert à définir des aspects spécifiques tels que le réglage de l'intervalle de diffusion 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 l’ QLowEnergyAdvertisingData ion seront visibles par les autres appareils qui effectuent actuellement une recherche. Ceux-ci peuvent s’en servir pour décider s’ils souhaitent établir une connexion ou non. Dans notre exemple, nous indiquons le type de service que nous proposons, un nom décrivant clairement notre appareil pour les utilisateurs, ainsi que la puissance d’émission de l’appareil. Cette dernière information est souvent utile aux clients potentiels, car elle leur permet d’estimer la distance à laquelle se trouve notre appareil en comparant l’intensité du signal reçu à celle annoncée.
Remarque : l’espace disponible pour les données de diffusion est très limité (seulement 31 octets au total) ; les données de longueur variable, telles que le nom de l’appareil, doivent donc ê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
Nous configurons ensuite le type de service que nous souhaitons proposer. Nous utilisons le service « Heart Rate » tel que défini dans la spécification Bluetooth sous sa forme minimale, c’est-à-dire composé uniquement de la caractéristique « Heart Rate Measurement ». Cette caractéristique doit prendre en charge la propriété « Notify » (et aucune autre), et elle doit disposer d’un descripteur « Client Characteristic Configuration », qui permet aux clients de s’enregistrer pour être informés des modifications apportées aux valeurs des caractéristiques. Nous fixons la valeur initiale de la fréquence cardiaque à zéro, car elle ne peut de toute façon pas être lue (le client ne peut obtenir cette valeur que 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);Publication et écoute des connexions entrantes
Maintenant que toutes les données ont été configurées, nous pouvons commencer la diffusion. Nous créons d’abord un objet ` QLowEnergyController ` dans ` peripheral role ` et l’utilisons pour créer un objet ` QLowEnergyService ` (dynamique) à partir de notre ` QLowEnergyServiceData` (statique). Ensuite, nous appelons la méthode ` QLowEnergyController::startAdvertising()`. Notez que nous transmettons notre QLowEnergyAdvertisingData à deux reprises : le premier argument sert de données de publicité proprement dites, le second de données de réponse à l’analyse. Ils pourraient transporter des informations différentes, mais cela n’est pas nécessaire dans le cas présent. Nous transmettons également une instance d’ QLowEnergyAdvertisingParameters construite par défaut, car les paramètres de diffusion par défaut nous conviennent. Si un client est intéressé par le service diffusé, il peut désormais établir une connexion avec notre appareil. Lorsque cela se produit, l’appareil cesse de diffuser et le signal ` QLowEnergyController::connected()` est émis.
Remarque : lorsqu’un client se déconnecte, la diffusion ne reprend pas automatiquement. Si vous souhaitez 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 accède-t-il concrètement à la fréquence cardiaque ? Cela se fait en mettant régulièrement à jour la valeur de la caractéristique correspondante dans l'objet QLowEnergyService que nous avons reçu de l'QLowEnergyController, comme dans l'extrait de code ci-dessus. La fréquence cardiaque provient généralement d’un capteur, mais dans notre exemple, nous inventons simplement des valeurs que nous faisons osciller entre 60 et 100. L’élément le plus important dans l’extrait de code suivant est l’appel à ` QLowEnergyService::writeCharacteristic`. Si un client est actuellement connecté et a activé les notifications en écrivant dans l’ Client Characteristic Configuration susmentionné, 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.