📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

 
(同じ利用者による、間の11版が非表示)
144行目: 144行目:
* AD Data (可変長)
* AD Data (可変長)
<br>
<br>
[[ファイル:Qt BLE 3.png|フレームなし|中央]]
<br>
==== その他 (通信特性 / セキュリティ等) ====
==== その他 (通信特性 / セキュリティ等) ====
* 通信特性
* 通信特性
165行目: 168行目:
<br>
<br>
==== 使用例 ====
==== 使用例 ====
Qt Bluetoothモジュールを使用したBLEスキャンの処理を以下に示す。<br>
<br>
* QBluetoothDeviceDiscoveryAgentクラス
* QBluetoothDeviceInfoクラス
<br>
===== デバイス探索エージェントの作成 =====
QBluetoothDeviceDiscoveryAgentのインスタンスを生成する。<br>
<br>
<syntaxhighlight lang="c++">
#include <QBluetoothDeviceDiscoveryAgent>
QBluetoothDeviceDiscoveryAgent discoveryAgent;
</syntaxhighlight>
<br>
===== シグナル / スロット接続 =====
* QBluetoothDeviceDiscoveryAgent::deviceDiscoveredシグナル
*: デバイスを発見した時に送信される。
* QBluetoothDeviceDiscoveryAgent::finished
*: スキャンが完了した時に送信される。
* QBluetoothDeviceDiscoveryAgent::error
*: エラーが発生した時に送信される。
<br>
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
// デバイス発見時
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &MyClass::onDeviceDiscovered);
// スキャン完了時
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &MyClass::onScanFinished);
// エラー発生時
// エラーハンドリングは必ず実装する
connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::error, this, &MyClass::onError);
</syntaxhighlight>
<br>
===== スキャン開始 =====
<code>QBluetoothDeviceDiscoveryAgent::LowEnergyMethod</code>メソッドを指定して、<code>QBluetoothDeviceDiscoveryAgent::start</code>メソッドを実行する。<br>
これによりBLEデバイスのスキャンが開始する。<br>
<br>
<syntaxhighlight lang="c++">
discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
</syntaxhighlight>
<br>
===== デバイス発見時 =====
<code>QBluetoothDeviceDiscoveryAgent::deviceDiscovered</code>シグナルで通知する。<br>
<code>QBluetoothDeviceInfo</code>クラスを使用して、以下に示す情報を取得することが可能である。<br>
* デバイス名
* アドレス
* 信号強度 (RSSI値)
* サービスUUID
* マニファクチャラーデータ
<br>
<u>ただし、これらの情報を取得する前は、必ず存在確認を行う。</u><br>
<br>
<syntaxhighlight lang="c++">
void onDeviceDiscovered(const QBluetoothDeviceInfo &device)
{
    // デバイス名の取得
    QString name = device.name();
    // アドレスの取得
    QString address = device.address().toString();
    // RSSI値の取得
    qint16 rssi = device.rssi();
    // サービスUUIDの取得
    QList<QBluetoothUuid> services = device.serviceUuids();
    // マニファクチャラーデータの取得
    QMap<quint16, QByteArray> manufacturerData = device.manufacturerData();
}
</syntaxhighlight>
<br>
===== スキャン完了時 =====
<code>QBluetoothDeviceDiscoveryAgent::finished</code>シグナルで送信する。<br>
<br>
スキャン完了時の処理を記述する。<br>
また、必要に応じて再スキャンを開始する。<br>
<br>
<syntaxhighlight lang="c++">
void onScanFinished()
{
    // 必要に応じて再スキャン
    discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
}
</syntaxhighlight>
<br>
===== エラー発生時 =====
リソースの解放は適切に行う。<br>
<br>
<syntaxhighlight lang="c++">
void onError(QBluetoothDeviceDiscoveryAgent::Error error)
{
    switch (error) {
      case QBluetoothDeviceDiscoveryAgent::NoError:
            break;
      case QBluetoothDeviceDiscoveryAgent::InputOutputError:
            break;
      case QBluetoothDeviceDiscoveryAgent::PoweredOffError:
            break;
      case QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError:
            break;
      case QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError:
            break;
      case QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod:
            break;
      default:
            break;
    }
}
</syntaxhighlight>
<br>
===== スキャン停止 =====
<syntaxhighlight lang="c++">
discoveryAgent->stop();
</syntaxhighlight>
<br>
===== 組み合わせ =====
<syntaxhighlight lang="c++">
// BLEデバイスのスキャンを管理するクラス
// BLEデバイスの検出と監視, 継続的なスキャンモード, デバイス情報の重複排除, 自動リカバリを行う
  #include <QObject>
  #include <QObject>
  #include <QBluetoothDeviceDiscoveryAgent>
  #include <QBluetoothDeviceDiscoveryAgent>
  #include <QBluetoothDeviceInfo>
  #include <QBluetoothDeviceInfo>
#include <memory>
  #include <QTimer>
  #include <QTimer>
  #include <QDebug>
  #include <QDebug>
178行目: 301行目:
   
   
  private:
  private:
     std::unique_ptr<QBluetoothDeviceDiscoveryAgent> discoveryAgent;
     QBluetoothDeviceDiscoveryAgent discoveryAgent; // BLEデバイス探索用エージェント
     std::unique_ptr<QTimer> rescanTimer;
     QTimer rescanTimer;                             // 継続的スキャン用タイマ
     bool isContinuousScan = false;
     bool   isContinuousScan = false;               // 継続的スキャンモードのフラグ
    QMap<QBluetoothAddress, QBluetoothDeviceInfo> knownDevices;  // 既知デバイスのキャッシュ
   
   
    // デバイス探索エージェントとタイマーのシグナルを適切なスロットに接続
    // デバイス発見時の処理, スキャン完了時の処理, エラー発生時の処理, 定期的な再スキャンの制御を行う
     void connectSignals()
     void connectSignals()
     {
     {
       // デバイス探索エージェントのシグナル接続
       // デバイス探索エージェントのシグナル接続
       connect(discoveryAgent.get(), &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BLEDeviceScanner::onDeviceDiscovered);
       connect(&discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BLEDeviceScanner::onDeviceDiscovered);
       connect(discoveryAgent.get(), &QBluetoothDeviceDiscoveryAgent::finished, this, &BLEDeviceScanner::onScanFinished);
       connect(&discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &BLEDeviceScanner::onScanFinished);
       connect(discoveryAgent.get(), static_cast<void(QBluetoothDeviceDiscoveryAgent::*)(QBluetoothDeviceDiscoveryAgent::Error)>(&QBluetoothDeviceDiscoveryAgent::error),
       connect(&discoveryAgent, static_cast<void(QBluetoothDeviceDiscoveryAgent::*)(QBluetoothDeviceDiscoveryAgent::Error)>(&QBluetoothDeviceDiscoveryAgent::error),
               this, &BLEDeviceScanner::onError);
               this, &BLEDeviceScanner::onError);
   
   
       // 再スキャンタイマのシグナル接続
       // 再スキャンタイマのシグナル接続
       connect(rescanTimer.get(), &QTimer::timeout, this, [this]() {
       connect(&rescanTimer, &QTimer::timeout, this, [this]() {
           if (isContinuousScan) {
           if (isContinuousScan) {
             discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
             discoveryAgent.start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
           }
           }
       });
       });
     }
     }
   
   
    // エラーコード
     QString getErrorMessage(QBluetoothDeviceDiscoveryAgent::Error error)
     QString getErrorMessage(QBluetoothDeviceDiscoveryAgent::Error error)
     {
     {
208行目: 335行目:
           case QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod:  return "未対応の探索方法";
           case QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod:  return "未対応の探索方法";
           default:                                                          return "不明なエラー";
           default:                                                          return "不明なエラー";
      }
    }
    // 発見されたデバイスの詳細情報をログに出力
    // デバイス名, MACアドレス, 電波強度 (RSSI), 提供サービスのUUID, メーカー固有データを表示
    void logDeviceInfo(const QBluetoothDeviceInfo& device)
    {
      qDebug() << "BLEデバイスを発見:";
      qDebug() << "  名前:" << device.name();
      qDebug() << "  アドレス:" << device.address().toString();
      qDebug() << "  RSSI:" << device.rssi();
      // サービスUUIDのログ出力
      const QList<QBluetoothUuid> serviceUuids = device.serviceUuids();
      if (!serviceUuids.isEmpty()) {
          qDebug() << "  提供サービス:";
          for (const QBluetoothUuid& uuid : serviceUuids) {
            qDebug() << "    -" << uuid.toString();
          }
      }
      // マニファクチャラーデータのログ出力
      const QMap<quint16, QByteArray> manufacturerData = device.manufacturerData();
      if (!manufacturerData.isEmpty()) {
          qDebug() << "  マニファクチャラーデータ:";
          QMap<quint16, QByteArray>::const_iterator i = manufacturerData.constBegin();
          while (i != manufacturerData.constEnd()) {
            qDebug() << "    ID: " << i.key() << "データ: " << i.value().toHex();
            i++;
          }
       }
       }
     }
     }
214行目: 371行目:
     explicit BLEDeviceScanner(QObject* parent = nullptr) : QObject(parent)
     explicit BLEDeviceScanner(QObject* parent = nullptr) : QObject(parent)
     {
     {
      // デバイス探索エージェントの初期化
      discoveryAgent = std::make_unique<QBluetoothDeviceDiscoveryAgent>(this);
       // BLEデバイスのみをスキャンするように設定
       // BLEデバイスのみをスキャンするように設定
       discoveryAgent->setLowEnergyDiscoveryTimeout(10000);  // 10秒のタイムアウト
       discoveryAgent.setLowEnergyDiscoveryTimeout(10000);  // 10秒のタイムアウト
   
   
       // 自動再スキャンタイマの設定
       // 自動再スキャンタイマの設定
       rescanTimer = std::make_unique<QTimer>(this);
       rescanTimer.setInterval(30000);  // 30秒間隔で再スキャン
      rescanTimer->setInterval(30000);  // 30秒間隔で再スキャン
   
   
       connectSignals();
       connectSignals();
     }
     }
   
   
     // スキャンを開始
     // BLEデバイスのスキャンを開始
     void startScan(bool continuous = false)
     void startScan(bool continuous = false)
     {
     {
233行目: 386行目:
           qDebug() << "BLEデバイススキャンを開始...";
           qDebug() << "BLEデバイススキャンを開始...";
           isContinuousScan = continuous;
           isContinuousScan = continuous;
           discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
           discoveryAgent.start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
   
   
           if (continuous) rescanTimer->start();
           if (continuous) rescanTimer.start();
   
   
           emit scanStarted();
           emit scanStarted();
251行目: 404行目:
       try {
       try {
           qDebug() << "BLEデバイススキャンを停止...";
           qDebug() << "BLEデバイススキャンを停止...";
           discoveryAgent->stop();
           discoveryAgent.stop();
           rescanTimer->stop();
           rescanTimer.stop();
           isContinuousScan = false;
           isContinuousScan = false;
           emit scanStopped();
           emit scanStopped();
264行目: 417行目:
   
   
  signals:
  signals:
     void deviceDiscovered(const QBluetoothDeviceInfo& device);
     void deviceDiscovered(const QBluetoothDeviceInfo& device); // 新規デバイス発見時
     void scanStarted();
     void scanStarted();   // スキャン開始時
     void scanStopped();
     void scanStopped();   // スキャン停止時
     void scanFinished();
     void scanFinished();   // スキャン完了時
     void errorOccurred(const QString& error);
     void errorOccurred(const QString& error); // エラー発生時
   
   
  private slots:
  private slots:
    // デバイス発見時の処理
    // BLEデバイスのフィルタリング, 重複デバイスの検出と更新, デバイス情報のログ出力, 新規 / 更新デバイスの通知
     void onDeviceDiscovered(const QBluetoothDeviceInfo& device)
     void onDeviceDiscovered(const QBluetoothDeviceInfo& device)
     {
     {
       // BLEデバイスのみを処理
       // BLEデバイスのみを処理
      if (device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) {
        if (!(device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration)) {
          qDebug() << "BLEデバイスを発見:";
          return;
          qDebug() << "  名前:" << device.name();
        }
          qDebug() << "  アドレス:" << device.address().toString();
          qDebug() << "  RSSI:" << device.rssi();
   
   
          // アドバタイズメントデータの解析
        // デバイスの重複確認
          const QList<QBluetoothUuid> serviceUuids = device.serviceUuids();
        const QBluetoothAddress& address = device.address();
          if (!serviceUuids.isEmpty()) {
        if (!knownDevices.contains(address) || knownDevices[address].rssi() != device.rssi()) {
            qDebug() << "  提供サービス:";
            knownDevices[address] = device;
            for (const QBluetoothUuid& uuid : serviceUuids) {
                qDebug() << "    -" << uuid.toString();
            }
          }
   
   
          // マニファクチャラーデータの解析
            // デバイス情報のログ出力と通知
          const QMap<quint16, QByteArray> manufacturerData = device.manufacturerData();
            logDeviceInfo(device);
          if (!manufacturerData.isEmpty()) {
            emit deviceDiscovered(device);
            qDebug() << "  マニファクチャラーデータ:";
        }
            QMap<quint16, QByteArray>::const_iterator i = manufacturerData.constBegin();
            while (i != manufacturerData.constEnd()) {
                qDebug() << "    ID: " << i.key() << "データ: " << i.value().toHex();
                ++i;
            }
          }
          emit deviceDiscovered(device);
      }
     }
     }
   
   
    // スキャン完了時の処理
    // 完了通知の発行, 継続的スキャンモードの場合は1秒後に再スキャン
     void onScanFinished()
     void onScanFinished()
     {
     {
312行目: 454行目:
       if (isContinuousScan) {
       if (isContinuousScan) {
           QTimer::singleShot(1000, this, [this]() {
           QTimer::singleShot(1000, this, [this]() {
             discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
             discoveryAgent.start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
           });
           });
       }
       }
     }
     }
   
   
    // エラー発生時の処理 (エラーメッセージの生成とログ出力)
    // 継続的スキャンモードの場合は5秒後に自動再試行
     void onError(QBluetoothDeviceDiscoveryAgent::Error error)
     void onError(QBluetoothDeviceDiscoveryAgent::Error error)
     {
     {
326行目: 470行目:
       if (isContinuousScan) {
       if (isContinuousScan) {
           QTimer::singleShot(5000, this, [this]() {
           QTimer::singleShot(5000, this, [this]() {
             discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
             discoveryAgent.start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
           });
           });
       }
       }
385行目: 529行目:
<br>
<br>
==== 使用例 ====
==== 使用例 ====
===== QLowEnergyControllerクラスのインスタンスの生成 =====
まず、<code>QBluetoothDeviceDiscoveryAgent</code>クラスを使用して、スキャンを実行する。<br>
<br>
次に、接続するデバイスの<code>QBluetoothDeviceInfo</code>クラスのデバイス情報を取得する。<br>
取得したデバイス情報を元に、<code>QLowEnergyController</code>クラスのインスタンスを生成する。<br>
<br>
===== コントローラのシグナル / スロット接続 =====
最低限必要なシグナルを示す。<br>
* connected
*: デバイスへの接続完了を通知
* disconnected
*: デバイスとの切断を通知 
* serviceDiscovered
*: 新しいサービスの発見を通知
* discoveryFinished
*: サービス探索の完了を通知
<br>
===== BLEデバイスの接続 =====
connectToDeviceメソッドを実行してBLEデバイスに接続する。<br>
connectedシグナルの受信を待つ。<br>
<br>
===== サービスの探索 =====
BLEデバイスへ接続後、discoverServicesメソッドを実行してサービスの探索を開始する。<br>
<br>
* serviceDiscoveredシグナルで個々のサービスが見つかる度に通知される。
* discoveryFinishedシグナルで探索完了が通知される。
<br>
===== サービスの取得 =====
createServiceObjectメソッドをを実行して、探索で発見したサービスのQLowEnergyServiceオブジェクトを生成する。<br>
このオブジェクトを使用して、特性 (Characteristic) や ディスクリプタにアクセスできる。<br>
<br>
===== 組み合わせ =====
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
// BLEのサービス探索を管理するクラス
// BLEデバイスへの接続, サービスの探索と監視
  #include <QObject>
  #include <QObject>
  #include <QLowEnergyController>
  #include <QLowEnergyController>
  #include <QLowEnergyService>
  #include <QLowEnergyService>
  #include <QTimer>
  #include <QTimer>
#include <memory>
  #include <QDebug>
  #include <QDebug>
   
   
398行目: 576行目:
   
   
  private:
  private:
     std::unique_ptr<QLowEnergyController> controller;
     QLowEnergyController controller;       // BLE接続とサービス探索を制御するコントローラ
     std::unique_ptr<QTimer>               discoveryTimeout;
     QTimer              discoveryTimeout; // サービス探索のタイムアウトを管理するタイマ
   
   
    // コントローラの各種シグナルを接続
    // 接続 / 切断, サービス探索の進行状況, 状態変更, エラー
     void connectControllerSignals()
     void connectControllerSignals()
     {
     {
       connect(controller.get(), &QLowEnergyController::connected, this, &BLEServiceDiscovery::onConnected);
       connect(&controller, &QLowEnergyController::connected, this, &BLEServiceDiscovery::onConnected);
       connect(controller.get(), &QLowEnergyController::disconnected, this, &BLEServiceDiscovery::onDisconnected);
       connect(&controller, &QLowEnergyController::disconnected, this, &BLEServiceDiscovery::onDisconnected);
       connect(controller.get(), &QLowEnergyController::serviceDiscovered, this, &BLEServiceDiscovery::onServiceDiscovered);
       connect(&controller, &QLowEnergyController::serviceDiscovered, this, &BLEServiceDiscovery::onServiceDiscovered);
       connect(controller.get(), &QLowEnergyController::discoveryFinished, this, &BLEServiceDiscovery::onDiscoveryFinished);
       connect(&controller, &QLowEnergyController::discoveryFinished, this, &BLEServiceDiscovery::onDiscoveryFinished);
       connect(controller.get(), static_cast<void(QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error), this, &BLEServiceDiscovery::onError);
       connect(&controller, static_cast<void(QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error), this, &BLEServiceDiscovery::onError);
       connect(controller.get(), &QLowEnergyController::stateChanged, this, &BLEServiceDiscovery::onStateChanged);
       connect(&controller, &QLowEnergyController::stateChanged, this, &BLEServiceDiscovery::onStateChanged);
     }
     }
   
   
    // 個別のBLEサービスに対するシグナル
    // 状態変更とエラーイベントを監視してログを出力する
     void connectServiceSignals(QLowEnergyService *service)
     void connectServiceSignals(QLowEnergyService *service)
     {
     {
422行目: 604行目:
     }
     }
   
   
    // エラーコードの変換
     QString getErrorMessage(QLowEnergyController::Error error)
     QString getErrorMessage(QLowEnergyController::Error error)
     {
     {
478行目: 661行目:
     {
     {
       // タイムアウトタイマの初期化
       // タイムアウトタイマの初期化
       discoveryTimeout = std::make_unique<QTimer>(this);
       discoveryTimeout.setInterval(10000);  // 10秒のタイムアウト
      discoveryTimeout->setInterval(10000);  // 10秒のタイムアウト
       discoveryTimeout.setSingleShot(true);
       discoveryTimeout->setSingleShot(true);
   
   
       connect(discoveryTimeout.get(), &QTimer::timeout, this, &BLEServiceDiscovery::onDiscoveryTimeout);
       connect(&discoveryTimeout, &QTimer::timeout, this, &BLEServiceDiscovery::onDiscoveryTimeout);
     }
     }
   
   
     // デバイスへの接続とサービス探索の開始
     // デバイスへの接続とサービス探索の開始
     void startDiscovery(const QBluetoothDeviceInfo& device)
    // コントローラの初期化, シグナルの接続, デバイスへの接続開始, タイムアウトタイマの開始
     void startDiscovery(const QBluetoothDeviceInfo &device)
     {
     {
       try {
       try {
492行目: 675行目:
   
   
           // コントローラの初期化
           // コントローラの初期化
          controller = std::make_unique<QLowEnergyController>(device, this);
           connectControllerSignals();
           connectControllerSignals();
   
   
           // 接続開始
           // 接続開始
           controller->connectToDevice();
           controller.connectToDevice();
           discoveryTimeout->start();
           discoveryTimeout.start();
       }
       }
       catch (const std::exception &e) {
       catch (const std::exception &e) {
506行目: 688行目:
     }
     }
   
   
     // 探索を停止
     // 探索を停止 (タイムアウトタイマも停止)
     void stopDiscovery()
     void stopDiscovery()
     {
     {
       try {
       try {
           if (controller) {
           if (controller) {
             controller->disconnectFromDevice();
             controller.disconnectFromDevice();
             discoveryTimeout->stop();
             discoveryTimeout.stop();
           }
           }
       }
       }
523行目: 705行目:
   
   
  signals:
  signals:
     void serviceDiscovered(QLowEnergyService *service);
     void serviceDiscovered(QLowEnergyService *service); // 新しいサービスが発見された時に発行
     void discoveryComplete();
     void discoveryComplete();                           // 全てのサービス探索が完了した時に発行
     void errorOccurred(const QString &error);
     void errorOccurred(const QString &error);           // エラーが発生した時に発行
     void connectionStateChanged(QLowEnergyController::ControllerState state);
     void connectionStateChanged(QLowEnergyController::ControllerState state); // 接続状態が変更された時に発行
   
   
  private slots:
  private slots:
    // デバイスへの接続が完了した時 (タイムアウトタイマを停止して、サービス探索を開始)
     void onConnected()
     void onConnected()
     {
     {
       qDebug() << "デバイスに接続";
       qDebug() << "デバイスに接続";
       discoveryTimeout->stop();
       discoveryTimeout.stop();
   
   
       // サービス探索の開始
       // サービス探索の開始
       controller->discoverServices();
       controller.discoverServices();
     }
     }
   
   
    // デバイスから切断された時 (タイムアウトタイマを停止)
     void onDisconnected()
     void onDisconnected()
     {
     {
       qDebug() << "デバイスから切断";
       qDebug() << "デバイスから切断";
       discoveryTimeout->stop();
       discoveryTimeout.stop();
     }
     }
   
   
    // 新しいサービスが発見された時
     void onServiceDiscovered(const QBluetoothUuid& uuid)
     void onServiceDiscovered(const QBluetoothUuid& uuid)
     {
     {
549行目: 734行目:
   
   
       // サービスオブジェクトの作成
       // サービスオブジェクトの作成
       QLowEnergyService* service = controller->createServiceObject(uuid, this);
       QLowEnergyService* service = controller.createServiceObject(uuid, this);
       if (service) {
       if (service) {
           connectServiceSignals(service);
           connectServiceSignals(service);
556行目: 741行目:
     }
     }
   
   
    // サービス探索が完了した時
     void onDiscoveryFinished()
     void onDiscoveryFinished()
     {
     {
       qDebug() << "サービス探索が完了";
       qDebug() << "サービス探索が完了";
       discoveryTimeout->stop();
       discoveryTimeout.stop();
       emit discoveryComplete();
       emit discoveryComplete();
     }
     }
   
   
    // エラーが発生した時
     void onError(QLowEnergyController::Error error)
     void onError(QLowEnergyController::Error error)
     {
     {
570行目: 757行目:
     }
     }
   
   
    // タイムアウトが発生した時 (探索を停止して、エラーとして通知)
     void onDiscoveryTimeout()
     void onDiscoveryTimeout()
     {
     {
577行目: 765行目:
     }
     }
   
   
    // 接続状態が変更された時 (状態の変更をログ出力して、通知)
     void onStateChanged(QLowEnergyController::ControllerState state)
     void onStateChanged(QLowEnergyController::ControllerState state)
     {
     {
651行目: 840行目:
<br>
<br>
==== 使用例 ====
==== 使用例 ====
===== ローカルデバイスの初期化 =====
BLEデバイスを利用するため、QBluetoothLocalDeviceクラスを使用して初期化する。<br>
初期化時にBLEデバイスが有効かどうかの確認を行う。<br>
<br>
* QBluetoothLocalDeviceクラス
* QBluetoothAddressクラス
<br>
<syntaxhighlight lang="c++">
#include <QBluetoothLocalDevice>
#include <QBluetoothAddress>
QBluetoothLocalDevice localDevice;
if (!localDevice.isValid()) {
    qDebug() << "Bluetoothデバイスが利用できません";
    return;
}
</syntaxhighlight>
<br>
===== ペアリング状態の変化を監視 =====
ペアリングの結果を受信すため、<code>QBluetoothLocalDevice::pairingFinished</code>シグナルに接続する。<br>
これにより、ペアリング成功 / 失敗の通知を受け取ることができる。<br>
<br>
<syntaxhighlight lang="c++">
connect(&localDevice, &QBluetoothLocalDevice::pairingFinished, [](const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing) {
    if (pairing == QBluetoothLocalDevice::Paired) {
      qDebug() << "ペアリング成功:" << address.toString();
    }
    else {
      qDebug() << "ペアリング失敗:" << address.toString();
    }
});
</syntaxhighlight>
<br>
===== PINコード確認のシグナル (必要な場合のみ) =====
PINコードが必要なデバイスは、<code>BluetoothLocalDevice::pairingDisplayConfirmation</code>シグナルに接続する。<br>
これにより、PINコードの確認が必要な場合に通知を受け取ることができる。<br>
<br>
<syntaxhighlight lang="c++">
connect(&localDevice, &QBluetoothLocalDevice::pairingDisplayConfirmation, [](const QBluetoothAddress &address, QString pin) {
    qDebug() << "PINコード確認: " << address.toString() << pin;
});
</syntaxhighlight>
<br>
===== ペアリング要求 =====
ペアリングを開始するため、ペアリングするデバイスのBluetoothアドレスを指定して、<code>QBluetoothLocalDevice::requestPairing</code>メソッドを実行する。<br>
<br>
ペアリングの結果は、<code>QBluetoothLocalDevice::pairingFinished</code>シグナルで受信して、成功 / 失敗に応じた処理を行う。<br>
<br>
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
QBluetoothAddress targetAddress("XX:XX:XX:XX:XX:XX"); // 接続先アドレス
localDevice.requestPairing(targetAddress, QBluetoothLocalDevice::Paired);
</syntaxhighlight>
<br>
===== 組み合わせ =====
<syntaxhighlight lang="c++">
// BLEデバイスとのペアリング操作を管理するクラス
// ペアリングの開始と解除, ペアリング状態の監視, PINコード認証
  #include <QObject>
  #include <QObject>
  #include <QBluetoothLocalDevice>
  #include <QBluetoothLocalDevice>
  #include <QBluetoothAddress>
  #include <QBluetoothAddress>
#include <memory>
  #include <QDebug>
  #include <QDebug>
   
   
663行目: 908行目:
   
   
  private:
  private:
     std::unique_ptr<QBluetoothLocalDevice> localDevice;
     QBluetoothLocalDevice localDevice; // ローカルのBLEデバイスを管理するオブジェクト
   
   
    // ペアリング状態を表す文字列
     QString getPairingStatusString(QBluetoothLocalDevice::Pairing status)
     QString getPairingStatusString(QBluetoothLocalDevice::Pairing status)
     {
     {
673行目: 919行目:
           default:                                      return "不明な状態";
           default:                                      return "不明な状態";
       }
       }
    }
    // BLEデバイスが使用可能な状態かどうかを確認
    bool isDeviceReady() const
    {
      if (!localDevice || !localDevice->isValid()) return false;
      return localDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff;
    }
    // BLEデバイスのホストモードを設定
    void setHostMode(QBluetoothLocalDevice::HostMode mode)
    {
      if (isDeviceReady()) localDevice.setHostMode(mode);
    }
    // ホスト側においてBLEが利用可能かどうかを確認
    bool isBluetoothAvailable() const
    {
      return QBluetoothLocalDevice::allDevices().count() > 0;
     }
     }
   
   
  public:
  public:
     explicit BLEPairing(QObject* parent = nullptr) : QObject(parent)
     explicit BLEPairing(QObject *parent = nullptr) : QObject(parent)
     {
     {
       try {
       try {
          // ローカルデバイスの初期化
          localDevice = std::make_unique<QBluetoothLocalDevice>(this);
           // シグナルの接続
           // シグナルの接続
           connect(localDevice.get(), &QBluetoothLocalDevice::pairingFinished, this, &BLEPairing::onPairingFinished);
           connect(&localDevice, &QBluetoothLocalDevice::pairingFinished, this, &BLEPairing::onPairingFinished);
           connect(localDevice.get(), &QBluetoothLocalDevice::error, this, &BLEPairing::onError);
           connect(&localDevice, &QBluetoothLocalDevice::error, this, &BLEPairing::onError);
           connect(localDevice.get(), &QBluetoothLocalDevice::pairingDisplayConfirmation, this, &BLEPairing::onPairingDisplayConfirmation);
           connect(&localDevice, &QBluetoothLocalDevice::pairingDisplayConfirmation, this, &BLEPairing::onPairingDisplayConfirmation);
           connect(localDevice.get(), &QBluetoothLocalDevice::pairingDisplayPinCode, this, &BLEPairing::onPairingDisplayPinCode);
           connect(&localDevice, &QBluetoothLocalDevice::pairingDisplayPinCode, this, &BLEPairing::onPairingDisplayPinCode);
       }
       }
       catch (const std::exception &e) {
       catch (const std::exception &e) {
694行目: 956行目:
     }
     }
   
   
     // ペアリングを開始
     ~BLEPairing()
    {
      if (localDevice) {
          disconnect(&localDevice);  // 全ての接続を解除
      }
    }
    // 指定したデバイスとのペアリングを開始
    // 30秒のタイムアウトを設定 (失敗時はエラーを通知)
     void requestPairing(const QBluetoothAddress &address)
     void requestPairing(const QBluetoothAddress &address)
     {
     {
       try {
       try {
           if (!localDevice->isValid()) {
           if (!isDeviceReady()) {
             emit errorOccurred("ローカルBluetoothデバイスが無効です");
             emit errorOccurred("ローカルBluetoothデバイスが無効です");
             return;
             return;
           }
           }
          // タイムアウトの設定
          QTimer::singleShot(30000, this, [this, address]() {
            if (getPairingStatus(address) != QBluetoothLocalDevice::Paired) {
                emit errorOccurred("ペアリングがタイムアウトしました");
            }
          });
   
   
           qDebug() << "ペアリングを開始: " << address.toString();
           qDebug() << "ペアリングを開始: " << address.toString();
           localDevice->requestPairing(address, QBluetoothLocalDevice::Paired);
           localDevice.requestPairing(address, QBluetoothLocalDevice::Paired);
       }
       }
       catch (const std::exception &e) {
       catch (const std::exception &e) {
           QString errorMsg = QString("ペアリング開始エラー: %1").arg(e.what());
           emit errorOccurred("ペアリング開始時に予期せぬエラーが発生しました");
          qDebug() << errorMsg;
          emit errorOccurred(errorMsg);
       }
       }
     }
     }
   
   
     // ペアリングを解除
     // 指定したBLEデバイスとのペアリングを解除
     void removePairing(const QBluetoothAddress& address)
     void removePairing(const QBluetoothAddress& address)
     {
     {
       try {
       try {
           if (!localDevice->isValid()) {
           if (!localDevice.isValid()) {
             emit errorOccurred("ローカルBluetoothデバイスが無効");
             emit errorOccurred("ローカルBluetoothデバイスが無効");
             return;
             return;
723行目: 998行目:
   
   
           qDebug() << "ペアリングを解除: " << address.toString();
           qDebug() << "ペアリングを解除: " << address.toString();
           localDevice->requestPairing(address, QBluetoothLocalDevice::Unpaired);
           localDevice.requestPairing(address, QBluetoothLocalDevice::Unpaired);
       }
       }
       catch (const std::exception &e) {
       catch (const std::exception &e) {
732行目: 1,007行目:
     }
     }
   
   
     // ペアリング状態を確認
     // 指定したBLEデバイスとのペアリング状態を確認
     QBluetoothLocalDevice::Pairing getPairingStatus(const QBluetoothAddress &address)
     QBluetoothLocalDevice::Pairing getPairingStatus(const QBluetoothAddress &address)
     {
     {
       try {
       try {
           if (!localDevice->isValid()) {
           if (!localDevice.isValid()) {
             emit errorOccurred("ローカルBluetoothデバイスが無効");
             emit errorOccurred("ローカルBluetoothデバイスが無効");
             return QBluetoothLocalDevice::Unpaired;
             return QBluetoothLocalDevice::Unpaired;
           }
           }
   
   
           return localDevice->pairingStatus(address);
           return localDevice.pairingStatus(address);
       }
       }
       catch (const std::exception &e) {
       catch (const std::exception &e) {
752行目: 1,027行目:
   
   
  signals:
  signals:
     void pairingComplete(const QBluetoothAddress& address, bool success);
     void pairingComplete(const QBluetoothAddress& address, bool success);             // ペアリング完了通知
     void pairingConfirmationRequired(const QBluetoothAddress& address, QString pin);
     void pairingConfirmationRequired(const QBluetoothAddress& address, QString pin); // PIN確認要求通知
     void errorOccurred(const QString& error);
     void errorOccurred(const QString& error); // エラー通知
   
   
  private slots:
  private slots:
    // ペアリング完了時
     void onPairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
     void onPairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
     {
     {
764行目: 1,040行目:
     }
     }
   
   
    // BLEエラー発生時
     void onError()
     void onError()
     {
     {
       QString errorMsg = "Bluetoothデバイスでエラーが発生";
      QBluetoothLocalDevice::Error error = localDevice->error();
       qDebug() << errorMsg;
       QString errorMsg;
      switch (error) {
          case QBluetoothLocalDevice::NoError:
            errorMsg = "エラーなし";
            break;
          case QBluetoothLocalDevice::PairingError:
            errorMsg = "ペアリングエラー";
            break;
          case QBluetoothLocalDevice::UnknownError:
          default:
            errorMsg = "不明なエラー";
            break;
      }
       qDebug() << "Bluetoothエラー: " << errorMsg;
       emit errorOccurred(errorMsg);
       emit errorOccurred(errorMsg);
     }
     }
   
   
    // ペアリング時のPIN確認要求処理
     void onPairingDisplayConfirmation(const QBluetoothAddress &address, QString pin)
     void onPairingDisplayConfirmation(const QBluetoothAddress &address, QString pin)
     {
     {
779行目: 1,072行目:
     }
     }
   
   
    // PINコード表示要求時
     void onPairingDisplayPinCode(const QBluetoothAddress &address, QString pin)
     void onPairingDisplayPinCode(const QBluetoothAddress &address, QString pin)
     {
     {
813行目: 1,107行目:
  #include <QLowEnergyCharacteristic>
  #include <QLowEnergyCharacteristic>
  #include <QTimer>
  #include <QTimer>
#include <memory>
  #include <QDebug>
  #include <QDebug>
   
   
821行目: 1,114行目:
   
   
  private:
  private:
     std::unique_ptr<QLowEnergyController> controller;
     QLowEnergyController controller;
     std::unique_ptr<QTimer> reconnectTimer;
     QTimer               reconnectTimer;
     QBluetoothDeviceInfo currentDevice;
     QBluetoothDeviceInfo currentDevice;
     bool autoReconnect = false;
     bool autoReconnect = false;
828行目: 1,121行目:
     void connectControllerSignals()
     void connectControllerSignals()
     {
     {
       connect(controller.get(), &QLowEnergyController::connected, this, &BLEConnection::onConnected);
       connect(&controller, &QLowEnergyController::connected, this, &BLEConnection::onConnected);
       connect(controller.get(), &QLowEnergyController::disconnected, this, &BLEConnection::onDisconnected);
       connect(&controller, &QLowEnergyController::disconnected, this, &BLEConnection::onDisconnected);
       connect(controller.get(), &QLowEnergyController::serviceDiscovered, this, &BLEConnection::onServiceDiscovered);
       connect(&controller, &QLowEnergyController::serviceDiscovered, this, &BLEConnection::onServiceDiscovered);
       connect(controller.get(), static_cast<void(QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error), this, &BLEConnection::onError);
       connect(&controller, static_cast<void(QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error), this, &BLEConnection::onError);
       connect(controller.get(), &QLowEnergyController::stateChanged, this, &BLEConnection::onStateChanged);
       connect(&controller, &QLowEnergyController::stateChanged, this, &BLEConnection::onStateChanged);
     }
     }
   
   
943行目: 1,236行目:
     {
     {
       // 再接続タイマの初期化
       // 再接続タイマの初期化
       reconnectTimer = std::make_unique<QTimer>(this);
       reconnectTimer.setInterval(5000);  // 5秒間隔で再接続
      reconnectTimer->setInterval(5000);  // 5秒間隔で再接続
       reconnectTimer.setSingleShot(true);
       reconnectTimer->setSingleShot(true);


       connect(reconnectTimer.get(), &QTimer::timeout, this, &BLEConnection::onReconnectTimeout);
       connect(&reconnectTimer &QTimer::timeout, this, &BLEConnection::onReconnectTimeout);
     }
     }
   
   
957行目: 1,249行目:


           // コントローラの初期化
           // コントローラの初期化
          controller = std::make_unique<QLowEnergyController>(device, this);
           connectControllerSignals();
           connectControllerSignals();


           // 接続パラメータの設定
           // 接続パラメータの設定
           controller->setRemoteAddressType(QLowEnergyController::PublicAddress);
           controller.setRemoteAddressType(QLowEnergyController::PublicAddress);


           // 接続開始
           // 接続開始
           controller->connectToDevice();
           controller.connectToDevice();
           currentDevice = device;
           currentDevice = device;
       }
       }
979行目: 1,270行目:
       try {
       try {
           if (controller) {
           if (controller) {
             controller->disconnectFromDevice();
             controller.disconnectFromDevice();
             reconnectTimer->stop();
             reconnectTimer.stop();
           }
           }
       }
       }
995行目: 1,286行目:
       autoReconnect = enable;
       autoReconnect = enable;
       if (!enable) {
       if (!enable) {
           reconnectTimer->stop();
           reconnectTimer.stop();
       }
       }
     }
     }
1,010行目: 1,301行目:
     {
     {
       qDebug() << "デバイスに接続";
       qDebug() << "デバイスに接続";
       reconnectTimer->stop();
       reconnectTimer.stop();
       emit connected();
       emit connected();
   
   
       // サービスの探索を開始
       // サービスの探索を開始
       controller->discoverServices();
       controller.discoverServices();
     }
     }
   
   
1,025行目: 1,316行目:
       if (autoReconnect) {
       if (autoReconnect) {
           qDebug() << "再接続を試行...";
           qDebug() << "再接続を試行...";
           reconnectTimer->start();
           reconnectTimer.start();
       }
       }
     }
     }
1,033行目: 1,324行目:
       qDebug() << "サービスを発見: " << uuid.toString();
       qDebug() << "サービスを発見: " << uuid.toString();
   
   
       QLowEnergyService* service = controller->createServiceObject(uuid, this);
       QLowEnergyService* service = controller.createServiceObject(uuid, this);
       if (service) {
       if (service) {
           connectServiceSignals(service);
           connectServiceSignals(service);
1,046行目: 1,337行目:
       emit errorOccurred(errorMessage);
       emit errorOccurred(errorMessage);
   
   
       if (autoReconnect && error != QLowEnergyController::InvalidBluetoothAdapterError) reconnectTimer->start();
       if (autoReconnect && error != QLowEnergyController::InvalidBluetoothAdapterError) reconnectTimer.start();
     }
     }


1,059行目: 1,350行目:
       if (autoReconnect && currentDevice.isValid()) {
       if (autoReconnect && currentDevice.isValid()) {
           qDebug() << "再接続を試行...";
           qDebug() << "再接続を試行...";
           controller->connectToDevice();
           controller.connectToDevice();
       }
       }
     }
     }
1,314行目: 1,605行目:
<br><br>
<br><br>


== BLE通信の使用例 ==
<syntaxhighlight lang="c++">
// BLEManager.hファイル
#include <QCoreApplication>
#include <QTimer>
#include <memory>
#include "bledevicescanner.h"
#include "bleservicediscovery.h"
#include "blepairing.h"
#include "bleconnection.h"
#include "bledatatransfer.h"
class BLEManager : public QObject
{
    Q_OBJECT
private:
    std::unique_ptr<BLEDeviceScanner>    scanner;
    std::unique_ptr<BLEServiceDiscovery> serviceDiscovery;
    std::unique_ptr<BLEPairing>          pairing;
    std::unique_ptr<BLEConnection>      connection;
    std::unique_ptr<BLEDataTransfer>    dataTransfer;
    QBluetoothDeviceInfo                targetDevice;
    std::unique_ptr<QTimer>              transferTimer;
    void connectSignals()
    {
      // スキャナのシグナル接続
        connect(scanner.get(), &BLEDeviceScanner::deviceDiscovered, this, &BLEManager::onDeviceDiscovered);
        connect(scanner.get(), &BLEDeviceScanner::errorOccurred, this, &BLEManager::onErrorOccurred);
        // ペアリングのシグナル接続
        connect(pairing.get(), &BLEPairing::pairingComplete, this, &BLEManager::onPairingComplete);
        connect(pairing.get(), &BLEPairing::errorOccurred, this, &BLEManager::onErrorOccurred);
        // 接続管理のシグナル接続
        connect(connection.get(), &BLEConnection::connected, this, &BLEManager::onConnected);
        connect(connection.get(), &BLEConnection::serviceDiscovered, this, &BLEManager::onServiceDiscovered);
        connect(connection.get(), &BLEConnection::errorOccurred, this, &BLEManager::onErrorOccurred);
        // データ転送のシグナル接続
        connect(dataTransfer.get(), &BLEDataTransfer::characteristicChanged, this, &BLEManager::onCharacteristicChanged);
        connect(dataTransfer.get(), &BLEDataTransfer::errorOccurred, this, &BLEManager::onErrorOccurred);
    }
    void startPeriodicDataTransfer()
    {
      transferTimer = std::make_unique<QTimer>(this);
      transferTimer->setInterval(1000);  // 1秒間隔
      connect(transferTimer.get(), &QTimer::timeout, this, [this]() {
          // サンプルデータの送信
          QByteArray data = generateSampleData();
          dataTransfer->writeCharacteristic(QBluetoothUuid(QString("YOUR_CHARACTERISTIC_UUID")), data );
      });
      transferTimer->start();
    }
    QByteArray generateSampleData()
    {
      // サンプルデータの生成 (実務では、適切なデータを生成)
      QByteArray data;
      data.append(0x01);  // コマンド
      data.append(0x02);  // データ長
      data.append(0x03);  // データ1
      data.append(0x04);  // データ2
      return data;
    }
    void processReceivedData(const QByteArray &data)
    {
      // 受信データの処理 (実務では、適切な処理を実装)
      if (data.isEmpty()) return;
      // データの解析例
      quint8 command = data.at(0);
      switch (command) {
          case 0x01:
            qDebug() << "コマンド1を受信";
            break;
          case 0x02:
            qDebug() << "コマンド2を受信";
            break;
          default:
            qDebug() << "不明なコマンド: " << command;
            break;
      }
    }
public:
    explicit BLEManager(QObject* parent = nullptr) : QObject(parent)
    {
      // 各コンポーネントの初期化
      scanner = std::make_unique<BLEDeviceScanner>(this);
      serviceDiscovery = std::make_unique<BLEServiceDiscovery>(this);
      pairing = std::make_unique<BLEPairing>(this);
      connection = std::make_unique<BLEConnection>(this);
      dataTransfer = std::make_unique<BLEDataTransfer>(this);
      connectSignals();
    }
    // デバイススキャンを開始
    void startDeviceScan()
    {
      qDebug() << "BLEデバイスのスキャンを開始...";
      scanner->startScan();
    }
private slots:
    void onDeviceDiscovered(const QBluetoothDeviceInfo& device)
    {
      // ターゲットデバイスかどうかを確認 (実務では、適切なフィルタリングが必要)
      if (device.name().contains("YourDeviceName", Qt::CaseInsensitive))
      {
          scanner->stopScan();
          targetDevice = device;
          qDebug() << "ターゲットデバイスを発見: " << device.name();
          // ペアリングを開始
          pairing->requestPairing(device.address());
      }
    }
    void onPairingComplete(const QBluetoothAddress &address, bool success)
    {
      if (success) {
          qDebug() << "ペアリング完了: 接続を開始...";
          connection->connectToDevice(targetDevice);
      }
      else {
          qDebug() << "ペアリングに失敗";
      }
    }
    void onConnected()
    {
      qDebug() << "デバイスに接続完了";
      connection->setAutoReconnect(true);  // 自動再接続を有効化
    }
    void onServiceDiscovered(QLowEnergyService *service)
    {
      qDebug() << "サービスを発見: " << service->serviceUuid().toString();
      // 対象のサービスかどうかを確認
      if (service->serviceUuid() == QBluetoothUuid(QString("YOUR_SERVICE_UUID"))) {
          dataTransfer->setService(service);
          // Notifyを有効化
          dataTransfer->enableNotifications(QBluetoothUuid(QString("YOUR_CHARACTERISTIC_UUID")));
          // 定期的なデータ送信を開始
          startPeriodicDataTransfer();
      }
    }
    void onCharacteristicChanged(const QBluetoothUuid &uuid, const QByteArray &value)
    {
      qDebug() << "データを受信:";
      qDebug() << "  UUID: " << uuid.toString();
      qDebug() << "  値: " << value.toHex();
      // 受信データの処理
      processReceivedData(value);
    }
    void onErrorOccurred(const QString &error)
    {
      qDebug() << "エラーが発生: " << error;
      // エラーに応じた適切な処理を実装
      // ...略
    }
};
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// main.cppファイル
#include <QCoreApplication>
#include "BLEManager.h"
int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    try {
      // BLEマネージャーオブジェクトの生成と開始
      auto bleManager = std::make_unique<BLEManager>();
      bleManager->startDeviceScan();
      return app.exec();
    }
    catch (const std::exception &e) {
      qDebug() << "致命的なエラーが発生: " << e.what();
      return -1;
    }
}
</syntaxhighlight>
<br><br>


{{#seo:
{{#seo: