Bluetooth Low Energy 心拍数サーバー
GATTサービスの設定およびアドバタイズ方法を実演する例です。この例では、 Qt Bluetooth 周辺機器(スレーブ)機能に関連するLow Energyクラスの使用方法を示しています。
Bluetooth Low Energy 心拍数サーバーは、 Qt Bluetooth APIを使用してBluetooth GATTサーバーを開発する方法を示すコマンドラインアプリケーションです。このアプリケーションでは、サービスの設定、そのアドバタイズ、および特性値の変更をクライアントに通知する方法について解説しています。
このサンプルでは、以下の Qt クラスが使用されています:
- QLowEnergyAdvertisingData
- QLowEnergyAdvertisingParameters
- QLowEnergyServiceData
- QLowEnergyCharacteristicData
- QLowEnergyDescriptorData
- QLowEnergyController
- QLowEnergyService
このサンプルはサーバーアプリケーションを実装しているため、グラフィカルユーザーインターフェースは備えていません。その動作を視覚的に確認するには、「Heart Rate Game」サンプルをご利用ください。これは、基本的にこのアプリケーションのクライアント側に対応するものです。
Bluetoothの権限の確認
アプリケーションがサービスを作成してアドバタイズを開始する前に、そのアプリケーションにBluetoothを使用する権限があるかどうかを確認する必要があります。
auto permissionStatus = app.checkPermission(QBluetoothPermission{});Bluetoothの権限をリクエストする
Bluetoothの認証ステータスが不明な場合は、Bluetoothを使用するための権限をリクエストする必要があります。
if(permissionStatus==Qt::PermissionStatus::Undetermined) {
qInfo("Requesting Bluetooth permission ...");
app.requestPermission(QBluetoothPermission{}, [&permissionStatus](constQPermission&permission){
qApp->exit();
permissionStatus=permission.status();
});
// ここで、権限リクエストの処理が完了するのを待ちます。
app.exec();
}広告データとパラメータの設定
広告プロセスの設定には、以下の2つのクラスが使用されます:
- QLowEnergyAdvertisingData は、どの情報を配信するかを指定します
- QLowEnergyAdvertisingParameters 広告間隔の設定や、接続を許可するデバイスの制御など、特定の側面を扱うために使用されます。
この例では、単にデフォルトのパラメータを使用しています。
QLowEnergyAdvertisingData に含まれる情報は、現在スキャンを行っている他のデバイスに表示されます。他のデバイスは、この情報に基づいて接続を確立するかどうかを判断できます。 この例では、提供するサービスの種類、人間にとってわかりやすいデバイス名、およびデバイスの送信電力レベルを含めています。送信電力レベルは、受信信号強度と広告されている信号強度を比較することで、デバイスがどのくらいの距離にあるかを判断できるため、潜在的なクライアントにとって役立つことがよくあります。
注: アドバタイズメントデータの容量 は非常に限られている(合計でわずか31バイト)ため、デバイス名などの可変長データはできるだけ短くする必要があります。
QLowEnergyAdvertisingData advertisingData;
advertisingData.setDiscoverability(QLowEnergyAdvertisingData::DiscoverabilityGeneral);
advertisingData.setIncludePowerLevel(true);
advertisingData.setLocalName("HeartRateServer");
advertisingData.setServices(QList<QBluetoothUuid>() << QBluetoothUuid::ServiceClassUuid::HeartRate);サービスデータの設定
次に、提供したいサービスの種類を設定します。ここでは、Bluetooth仕様で定義されているHeart Rate サービスを、最小構成、つまりHeart Rate Measurement 特性のみで構成される形で使用します。この特性は、Notify プロパティ(他のプロパティは含まない)をサポートしている必要があり、また、クライアントが特性値の変更に関する通知を受け取るために登録できるようにするClient Characteristic Configuration 記述子を持つ必要があります。 初期の心拍数値はゼロに設定します。これは、この値はそもそも読み取ることができないためです(クライアントがこの値を取得できる唯一の方法は、通知を経由することのみです)。
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);アドバタイジングと着信接続のリスニング
すべてのデータ設定が完了したので、アドバタイジングを開始できます。まず、peripheral role 内でQLowEnergyController オブジェクトを作成し、それを使用して(静的な)QLowEnergyServiceData から(動的な)QLowEnergyService オブジェクトを作成します。その後、QLowEnergyController::startAdvertising()を呼び出します。QLowEnergyAdvertisingData を2回渡している点に注意してください。1つ目の引数は実際の広告データとして、2つ目の引数はスキャン応答データとして機能します。これらは異なる情報を伝達することも可能ですが、ここではその必要はありません。 また、デフォルトのアドバタイジングパラメータで十分であるため、QLowEnergyAdvertisingParameters のデフォルトコンストラクタで生成されたインスタンスも渡します。クライアントがアドバタイズされたサービスに関心を持っていれば、デバイスへの接続を確立できます。接続が確立されると、デバイスはアドバタイジングを停止し、QLowEnergyController::connected()シグナルが発信されます。
注: クライアントが切断しても 、アドバタイジングは自動的に再開されません。自動的に再開させたい場合は、QLowEnergyController::disconnected()シグナルに接続し、対応するスロット内でQLowEnergyController::startAdvertising()を呼び出す必要があります。
boolerrorOccurred= false;
conststd::unique_ptr<QLowEnergyController>leController(QLowEnergyController::createPeripheral());
autoerrorHandler= [&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;心拍数の提供
ここまでは順調です。しかし、クライアントは実際にどのように心拍数を取得するのでしょうか?これは、上記のコードスニペットでQLowEnergyController から受け取ったQLowEnergyService オブジェクト内の、対応する特性の値を定期的に更新することで行われます。 心拍数のソースは通常、何らかのセンサーですが、この例では、60から100の間で変動する値を任意に生成しています。 以下のコードスニペットで最も重要な部分は、QLowEnergyService::writeCharacteristic への呼び出しです。クライアントが現在接続されており、前述のClient Characteristic Configuration への書き込みによって通知を有効にしている場合、新しい値について通知を受け取ります。
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.