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

 
(同じ利用者による、間の2版が非表示)
893行目: 893行目:
Classic Bluetoothでは、<code>QBluetoothSocket</code>クラスを使用して、<br>
Classic Bluetoothでは、<code>QBluetoothSocket</code>クラスを使用して、<br>
<code>connect</code>メソッドでソケット接続、<code>write</code>メソッド / <code>read</code>メソッドでデータの送受信を行う。<br>
<code>connect</code>メソッドでソケット接続、<code>write</code>メソッド / <code>read</code>メソッドでデータの送受信を行う。<br>
<br>
接続の確立と維持を行う処理は、全ての操作が非同期で行われる。<br>
そのため、各段階でのシグナル / スロット接続による状態管理が重要になる。<br>
<br>
==== 接続の確立 ====
<code>QBluetoothSocket</code>クラスのインスタンスを生成する。<br>
この時、RFCOMMプロトコルを指定する。<br>
<br>
デバイスのMACアドレスとポート番号を指定して、<code>QBluetoothSocket::connectToService</code>メソッドを実行する。<br>
接続状態の変化を監視するためのシグナル / スロット接続を設定する。<br>
<br>
<br>
  <syntaxhighlight lang="c++">
  <syntaxhighlight lang="c++">
  #include <QBluetoothSocket>
  #include <QBluetoothSocket>
  #include <QDebug>
  #include <QDebug>
  #include <memory>
QBluetoothSocket socket(QBluetoothServiceInfo::RfcommProtocol);
connect(&socket, &QBluetoothSocket::connected, []() {
    qDebug() << "接続成功";
});
connect(&socket, &QBluetoothSocket::stateChanged, [](QBluetoothSocket::SocketState state) {
    qDebug() << "状態変更:" << state;
});
connect(&socket, &QBluetoothSocket::errorOccurred, [](QBluetoothSocket::SocketError error) {
    qDebug() << "エラー発生:" << error;
});
</syntaxhighlight>
<br>
RFCOMM (Radio Frequency Communication) とは、Bluetooth Classicで使用される重要なプロトコルの1つである。<br>
RFCOMMプロトコルの特徴を以下に示す。<br>
* シリアルポート通信をエミュレートするプロトコル
* RS-232C通信の代替として設計
* 信頼性の高い双方向通信を提供
* 最大60個の同時接続をサポート
<br>
Qtで使用可能な他のBluetoothプロトコルを以下に示す。<br>
* L2CAP (Logical Link Control and Adaptation Protocol)
*: 低レイヤーのプロトコル
*: RFCOMMの基盤となるプロトコル
*: より高速なデータ転送が可能
*: 生のデータパケット送受信に使用
*: <br>
* RFCOMM
*: 最も使用される。
*: シリアルポートエミュレーション
*: 多くのBluetooth機器で採用されている。
*: 多くのBluetooth通信では、使いやすさと互換性の高さからRFCOMMが選択される。
<br>
<syntaxhighlight lang="c++">
// RFCOMMプロトコルを指定する場合
// シリアル通信が必要な場合 あるいは 安定性が重要な場合
QBluetoothSocket socket(QBluetoothServiceInfo::RfcommProtocol);
// L2CAPプロトコルを指定する場合
// 高速な通信が必要な場合 あるいは 低レベルの制御が必要な場合
QBluetoothSocket socket(QBluetoothServiceInfo::L2capProtocol);
</syntaxhighlight>
<br>
==== 接続の維持 ====
<code>QBluetoothSocket::connected</code>シグナルを受信して、接続成功を確認する。<br>
<br>
<code>QBluetoothSocket::stateChanged</code>シグナルを監視して、接続状態の変化を検知する。<br>
<br>
<code>QBluetoothSocket::errorOccurred</code>シグナルを監視してエラーを検知する。<br>
<br>
また、必要に応じて定期的なキープアライブメッセージを送信する。<br>
<br>
<syntaxhighlight lang="c++">
QBluetoothAddress address("XX:XX:XX:XX:XX:XX");
socket.connectToService(address, <ポート番号  例: 1>);
</syntaxhighlight>
<br>
==== データの送信 ====
<code>QBluetoothSocket::write</code>メソッドを使用してデータを送信する。<br>
<br>
<syntaxhighlight lang="c++">
QByteArray sendData = "Hello";
socket.write(sendData);
</syntaxhighlight>
<br>
==== データの受信 ====
# <code>QBluetoothSocket::readyRead</code>シグナルを受信してデータの到着を検知する。
# <code>QBluetoothSocket::readAll</code>メソッド、あるいは、<code>QBluetoothSocket::read</code>メソッドでデータを読む。
<br>
<syntaxhighlight lang="c++">
connect(&socket, &QBluetoothSocket::readyRead, []() {
    QByteArray data = socket.readAll();
    qDebug() << "受信データ: " << data;
});
</syntaxhighlight>
<br>
==== 切断処理 ====
# <code>QBluetoothSocket::disconnectFromService</code>メソッドを実行して、接続を終了する。
# <code>QBluetoothSocket::disconnected</code>シグナルを受信して切断完了を確認する。
# 必要に応じて、リソースの解放を実施する。
<br>
<syntaxhighlight lang="c++">
connect(&socket, &QBluetoothSocket::disconnected, []() {
    qDebug() << "切断完了";
});
// 切断を実行
socket.disconnectFromService();
</syntaxhighlight>
<br>
==== 組み合わせ ====
<syntaxhighlight lang="c++">
#include <QBluetoothSocket>
  #include <QDebug>
   
   
  class BluetoothConnection : public QObject
  class BluetoothConnection : public QObject
904行目: 1,010行目:
   
   
  private:
  private:
     std::unique_ptr<QBluetoothSocket> socket;
     QBluetoothSocket socket;
   
   
     // エラーコードを文字列に変換するヘルパー関数
     // エラーコード
     QString errorToString(QBluetoothSocket::SocketError error)
     QString errorToString(QBluetoothSocket::SocketError error)
     {
     {
920行目: 1,026行目:
     }
     }
   
   
     // 接続状態を文字列に変換するヘルパー関数
     // 接続状態
     QString stateToString(QBluetoothSocket::SocketState state)
     QString stateToString(QBluetoothSocket::SocketState state)
     {
     {
935行目: 1,041行目:
   
   
  public:
  public:
     explicit BluetoothConnection(QObject* parent = nullptr) : QObject(parent)
     explicit BluetoothConnection(QObject *parent = nullptr) : QObject(parent), socket(QBluetoothServiceInfo::RfcommProtocol, this)
     {
     {
       try {
       // 各種シグナルとスロットの接続
          // RFCOMMソケットの作成
      connect(&socket, &QBluetoothSocket::connected, this, &BluetoothConnection::onConnected);
          socket = std::make_unique<QBluetoothSocket>(QBluetoothServiceInfo::RfcommProtocol, this);
      connect(&socket, &QBluetoothSocket::disconnected, this, &BluetoothConnection::onDisconnected);
      connect(&socket, &QBluetoothSocket::errorOccurred, this, &BluetoothConnection::onError);
      connect(&socket, &QBluetoothSocket::readyRead, this, &BluetoothConnection::onDataReceived);
      connect(&socket, &QBluetoothSocket::stateChanged, this, &BluetoothConnection::onStateChanged);
    }
   
   
          // 各種シグナルとスロットの接続
    ~BluetoothConnection()
          connect(socket.get(), &QBluetoothSocket::connected, this, &BluetoothConnection::onConnected);
    {
          connect(socket.get(), &QBluetoothSocket::disconnected, this, &BluetoothConnection::onDisconnected);
       disconnect();
          connect(socket.get(), &QBluetoothSocket::errorOccurred, this, &BluetoothConnection::onError);
          connect(socket.get(), &QBluetoothSocket::readyRead, this, &BluetoothConnection::onDataReceived);
          connect(socket.get(), &QBluetoothSocket::stateChanged, this, &BluetoothConnection::onStateChanged);
      }
       catch (const std::exception &e) {
          qDebug() << "初期化エラー: " << e.what();
          throw;
      }
     }
     }
   
   
957行目: 1,059行目:
     void connectToDevice(const QBluetoothAddress &address, quint16 port)
     void connectToDevice(const QBluetoothAddress &address, quint16 port)
     {
     {
       try {
       if (socket.state() == QBluetoothSocket::ConnectedState) {
          if (socket->state() == QBluetoothSocket::ConnectedState) {
          qDebug() << "既に接続済み";
            qDebug() << "既に接続済み";
          return;
            return;
      }
          }
   
   
          qDebug() << "デバイスに接続します: " << address.toString();
      qDebug() << "デバイスに接続します: " << address.toString();
          qDebug() << "ポート: " << port;
      qDebug() << "ポート: " << port;
          socket->connectToService(address, port);
      socket.connectToService(address, port);
      }
      catch (const std::exception &e) {
          qDebug() << "接続エラー: " << e.what();
          throw;
      }
     }
     }
   
   
976行目: 1,072行目:
     void disconnect()
     void disconnect()
     {
     {
       try {
       if (socket.state() != QBluetoothSocket::UnconnectedState) {
          if (socket->state() != QBluetoothSocket::UnconnectedState) {
          qDebug() << "接続を切断...";
            qDebug() << "接続を切断...";
          socket.disconnectFromService();
            socket->disconnectFromService();
          }
      }
      catch (const std::exception &e) {
          qDebug() << "切断エラー: " << e.what();
          throw;
       }
       }
     }
     }
991行目: 1,081行目:
     bool sendData(const QByteArray &data)
     bool sendData(const QByteArray &data)
     {
     {
       try {
       if (socket.state() != QBluetoothSocket::ConnectedState) {
          if (socket->state() != QBluetoothSocket::ConnectedState) {
          qDebug() << "送信エラー: 接続されていません";
            qDebug() << "送信エラー: 接続されていません";
          return false;
            return false;
      }
          }
   
   
          qint64 bytesWritten = socket->write(data);
      qint64 bytesWritten = socket.write(data);
          if (bytesWritten == -1) {
      if (bytesWritten == -1) {
            qDebug() << "送信エラー: データの書き込みに失敗";
          qDebug() << "送信エラー: データの書き込みに失敗";
            return false;
          return false;
          }
      }
   
   
          qDebug() << bytesWritten << "バイトデータの送信完了";
      qDebug() << bytesWritten << "バイトデータの送信完了";
          return true;
      return true;
      }
      catch (const std::exception &e) {
          qDebug() << "送信エラー: " << e.what();
          throw;
      }
     }
     }
   
   
  private slots:
  private slots:
     // 接続確立時のスロット
     // 接続確立時
     void onConnected()
     void onConnected()
     {
     {
       qDebug() << "接続が確立";
       qDebug() << "接続が確立";
       qDebug() << "  ローカルアドレス:" << socket->localAddress().toString();
       qDebug() << "  ローカルアドレス:" << socket.localAddress().toString();
       qDebug() << "  リモートアドレス:" << socket->peerAddress().toString();
       qDebug() << "  リモートアドレス:" << socket.peerAddress().toString();
     }
     }
   
   
     // 切断時のスロット
     // 切断時
     void onDisconnected()
     void onDisconnected()
     {
     {
1,027行目: 1,111行目:
     }
     }
   
   
     // エラー発生時のスロット
     // エラー発生時
     void onError(QBluetoothSocket::SocketError error)
     void onError(QBluetoothSocket::SocketError error)
     {
     {
1,033行目: 1,117行目:
     }
     }
   
   
     // データ受信時のスロット
     // データ受信時
     void onDataReceived()
     void onDataReceived()
     {
     {
       QByteArray data = socket->readAll();
       QByteArray data = socket.readAll();
       qDebug() << "データを受信: " << data.size() << "バイト";
       qDebug() << "データを受信: " << data.size() << "バイト";
   
   
1,043行目: 1,127行目:
     }
     }
   
   
     // 接続状態変更時のスロット
     // 接続状態変更時
     void onStateChanged(QBluetoothSocket::SocketState state)
     void onStateChanged(QBluetoothSocket::SocketState state)
     {
     {