このページでは

Bluetooth Low Energy スキャナー

Bluetooth Low Energy周辺機器のコンテンツを閲覧するために設計されたアプリケーションです。このサンプルでは、すべての Qt Bluetooth Low Energyクラスの使用方法を示しています。

「Bluetooth Low Energy スキャナ」サンプルでは、 Qt Bluetooth APIを使用してBluetooth Low Energyアプリケーションを開発する方法を示しています。このアプリケーションでは、Low Energyデバイスのスキャン、サービスのスキャン、およびサービス特性や記述子の読み取りについて扱っています。

Qt BLEスキャナーを使用して検出されたGATTサービス

このサンプルでは、以下の Qt クラスが紹介されています:

このサンプルは、任意のBluetooth Low Energy周辺機器で使用できます。すべてのサービス、特性、および記述子のスナップショットを作成し、それらをユーザーに表示します。したがって、このアプリケーションを使用することで、周辺機器が提供するコンテンツを簡単に閲覧することができます。

例の動作確認

このサンプルは、以下の場所から実行できます:

Bluetoothの使用許可の要求

一部のプラットフォームでは、Bluetoothを使用するために明示的に権限を付与する必要があります。このサンプルでは、BluetoothPermission というQMLオブジェクトを使用して、権限を確認し、必要に応じて権限の要求を行います:

BluetoothPermission {
    id: permission
    communicationModes: BluetoothPermission.Access
    onStatusChanged: {
        if (permission.status === Qt.PermissionStatus.Denied)
            Device.update = "Bluetooth permission required"
        else if (permission.status === Qt.PermissionStatus.Granted)
            devicesPage.toggleDiscovery()
    }
}

ユーザーがデバイスの検出を開始しようとすると、権限要求ダイアログが表示され、権限ステータスは `Undetermined` となります:

onButtonClick: {
    if (permission.status === Qt.PermissionStatus.Undetermined)
        permission.request()
    else if (permission.status === Qt.PermissionStatus.Granted)
        devicesPage.toggleDiscovery()
}

ユーザーによって権限が付与されると、デバイス検出が開始されます。権限が付与されない場合、アプリケーションは機能しません。

デバイスのスキャン

最初のステップは、すべての周辺機器を検出することです。デバイスはQBluetoothDeviceDiscoveryAgent クラスを使用して検出できます。検出プロセスはstart()を使用して開始されます。新しいデバイスが検出されるたびに、deviceDiscovered()シグナルを通じて通知されます:

discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
discoveryAgent->setLowEnergyDiscoveryTimeout(25000);
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,
        this, &Device::addDevice);
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::errorOccurred,
        this, &Device::deviceScanError);
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished,
        this, &Device::deviceScanFinished);
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::canceled,
        this, &Device::deviceScanFinished);
discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);

以下のaddDevice() スロットは、新しいデバイスの検出に応答してトリガーされます。このスロットは、QBluetoothDeviceInfo::LowEnergyCoreConfiguration フラグを持つ検出されたすべてのデバイスをフィルタリングし、それらをユーザーに表示されるリストに追加します。deviceDiscovered()シグナルは、詳細情報が検出されるにつれて、同じデバイスに対して複数回発火する可能性があります。ここでは、ユーザーが個々のデバイスのみを確認できるように、これらのデバイス検出を照合しています:

void Device::addDevice(const QBluetoothDeviceInfo &info)
{
    if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) {
        auto devInfo = new DeviceInfo(info);
        auto it = std::find_if(devices.begin(), devices.end(),
                               [devInfo](DeviceInfo *dev) {
                                   return devInfo->getAddress() == dev->getAddress();
                               });
        if (it == devices.end()) {
            devices.append(devInfo);
        } else {
            auto oldDev = *it;
            *it = devInfo;
            delete oldDev;
        }
        emit devicesUpdated();
    }
}

デバイスのリストは、以下の画像のようになる場合があります。

注: リモートデバイスが自らの存在を能動的にアドバタイズしていることが前提条件となります 。

Qt BLEスキャナーに表示される周辺デバイス

サービスへの接続

ユーザーがリストからデバイスを選択すると、アプリケーションはそのデバイスに接続し、すべてのサービスをスキャンします。デバイスへの接続には、QLowEnergyController クラスが使用されます。QLowEnergyController::connectToDevice()関数は接続プロセスを開始し、このプロセスはQLowEnergyController::connected()シグナルを受信するか、エラーが発生するまで続きます:

if (!controller) {
    // Connecting signals and slots for connecting to LE services.
    controller = QLowEnergyController::createCentral(currentDevice.getDevice(), this);
    connect(controller, &QLowEnergyController::connected,
            this, &Device::deviceConnected);
    connect(controller, &QLowEnergyController::errorOccurred, this, &Device::errorReceived);
    connect(controller, &QLowEnergyController::disconnected,
            this, &Device::deviceDisconnected);
    connect(controller, &QLowEnergyController::serviceDiscovered,
            this, &Device::addLowEnergyService);
    connect(controller, &QLowEnergyController::discoveryFinished,
            this, &Device::serviceScanDone);
}

if (isRandomAddress())
    controller->setRemoteAddressType(QLowEnergyController::RandomAddress);
else
    controller->setRemoteAddressType(QLowEnergyController::PublicAddress);
controller->connectToDevice();

connected() シグナルによってトリガーされたスロットは、直ちにQLowEnergyController::discoverServices() を呼び出し、接続された周辺デバイスでのサービス検出を開始します。

controller->discoverServices();

その結果として得られたリストがユーザーに表示されます。下の画像は、SensorTagデバイスを選択した際の結果を示しています。この画面には、サービスの名前、プライマリサービスかセカンダリサービスかの区別、およびサービスタイプを決定するUUIDが一覧表示されています。

Qt BLEスキャナーを使用して検出されたGATTサービス

サービスが選択されるとすぐに、そのサービスとのやり取りを可能にするために、関連するQLowEnergyService インスタンスが作成されます:

QLowEnergyService*service = controller->createServiceObject(serviceUuid);
if(!service) {
    qWarning() << "Cannot create service for uuid";
   return;
}

サービスオブジェクトは、サービスの詳細の取得、特性や記述子の読み取りおよび書き込み、ならびにデータ変更通知の受信に必要なシグナルと関数を提供します。 変更通知は、値の書き込みの結果として、あるいは内部ロジックによって引き起こされる可能性のあるデバイス上の更新によってトリガーされることがあります。初期の詳細検索中、サービスのstate()は、RemoteService からRemoteServiceDiscovering へと遷移し、最終的にはRemoteServiceDiscovered で終了します:

connect(service, &QLowEnergyService::stateChanged,
        this, &Device::serviceDetailsDiscovered);
service->discoverDetails();
setUpdate(u"Back\n(Discovering details...)"_s);

サービスデータの読み取り

サービスを選択すると、そのサービスの詳細が表示されます。各特性は、名前、UUID、値、ハンドル、およびプロパティとともに一覧表示されます。

Qt BLE Scanner に記載されている GATT の特性

QLowEnergyService::characteristics() を使用してサービスの特性を取得することができ、さらにQLowEnergyCharacteristic::descriptors() を使用して各記述子を取得することができます。

const QList<QLowEnergyCharacteristic> chars = service->characteristics();
for (const QLowEnergyCharacteristic &ch : chars) {
    auto cInfo = new CharacteristicInfo(ch);
    m_characteristics.append(cInfo);
}

このサンプルアプリケーションでは記述子は表示されませんが、UUID だけでは個々の特性の名前を判別できない場合に、記述子を使用してその名前を取得しています。名前を取得する 2 つめの方法は、QBluetoothUuid::DescriptorType::CharacteristicUserDescription 型の記述子が存在することを利用する方法です。以下のコードは、その実現方法を示しています:

QString name = m_characteristic.name();
if (!name.isEmpty())
    return name;

// find descriptor with CharacteristicUserDescription
const QList<QLowEnergyDescriptor> descriptors = m_characteristic.descriptors();
for (const QLowEnergyDescriptor &descriptor : descriptors) {
    if (descriptor.type() == QBluetoothUuid::DescriptorType::CharacteristicUserDescription) {
        name = descriptor.value();
        break;
    }
}

サンプルプロジェクト @ 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.