ブルートゥース・ローエナジー・スキャナー

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

Bluetooth Low Energy Scanner Example は、Bluetooth Low Energy アプリケーションを Qt Bluetooth API.このアプリケーションでは、Low Energyデバイスのスキャン、サービスのスキャン、サービス特性と記述子の読み取りを行います。

この例では、以下の Qt クラスを紹介します:

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

例の実行

から例を実行するには Qt Creatorからサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Exampleを参照してください。

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();
    }
}

デバイスのリストは以下の画像のようになります。

注: リモート・デバイスが積極的にその存在をアドバタイズすることが前提条件です。

サービスへの接続

ユーザーがリストからデバイスを選択すると、アプリケーションはデバイスに接続し、すべてのサービスをスキャンします。デバイスへの接続には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が一覧表示されます。

サービスが選択されるとすぐに、関連するQLowEnergyService インスタンスが作成され、サービスとの対話が可能になります:

QLowEnergyServiceservice =  controller->createServiceObject(serviceUuid);if(!service) {*service =controller->createServiceObject(serviceUuid)    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、値、ハンドル、プロパティとともにリストされます。

サービスの特性は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

© 2025 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.