📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| (同じ利用者による、間の6版が非表示) | |||
| 269行目: | 269行目: | ||
QBluetoothDeviceDiscoveryAgent discoveryAgent; | QBluetoothDeviceDiscoveryAgent discoveryAgent; | ||
// | // デバイスタイプ | ||
QString deviceTypeToString(QBluetoothDeviceInfo::MajorDeviceClass type) | QString deviceTypeToString(QBluetoothDeviceInfo::MajorDeviceClass type) | ||
{ | { | ||
| 320行目: | 320行目: | ||
} | } | ||
// | // スキャンの開始 | ||
void startScan() | void startScan() | ||
{ | { | ||
| 333行目: | 333行目: | ||
} | } | ||
// | // スキャンの停止 | ||
void stopScan() | void stopScan() | ||
{ | { | ||
| 382行目: | 382行目: | ||
Classic Bluetoothでは、<code>QBluetoothServiceInfo</code>クラスを使用して、単純なサービス情報を管理する。<br> | Classic Bluetoothでは、<code>QBluetoothServiceInfo</code>クラスを使用して、単純なサービス情報を管理する。<br> | ||
<br> | <br> | ||
==== Bluetoothサービスディスカバリの準備 ==== | |||
<code>QBluetoothServiceDiscoveryAgent</code>クラスのインスタンスを生成する。<br> | |||
<br> | |||
以下に示すシグナルを接続する。 | |||
* QBluetoothServiceDiscoveryAgent::serviceDiscovered | |||
*: 発見したサービスを通知する。 | |||
* QBluetoothServiceDiscoveryAgent::finished | |||
*: 探索完了を通知する。 | |||
* QBluetoothServiceDiscoveryAgent::error | |||
*: エラー発生時の通知 | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
#include <QBluetoothServiceDiscoveryAgent> | |||
#include <QDebug> | |||
QBluetoothServiceDiscoveryAgent discoveryAgent; | |||
// シグナルとスロットの接続 | |||
connect(&discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, [](const QBluetoothServiceInfo &info) { | |||
qDebug() << "サービス発見"; | |||
}); | |||
connect(&discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, []() { | |||
qDebug() << "探索完了"; | |||
}); | |||
connect(&discoveryAgent, &QBluetoothServiceDiscoveryAgent::error, [](QBluetoothServiceDiscoveryAgent::Error error) { | |||
qDebug() << "エラー発生"; | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
==== サービスディスカバリの開始 ==== | |||
<code>QBluetoothAddress</code>クラスを使用して、対象デバイスのBluetoothアドレスを指定する。<br> | |||
<br> | |||
<code>QBluetoothServiceDiscoveryAgent::setRemoteAddress</code>メソッドを実行して、探索対象のデバイスを設定する。<br> | |||
<code>QBluetoothServiceDiscoveryAgent::start</code>メソッドを実行して、ディスカバリを開始する。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
#include <QBluetoothAddress> | |||
// デバイスのBluetoothアドレスを設定 | |||
QBluetoothAddress address("XX:XX:XX:XX:XX:XX"); | |||
discoveryAgent.setRemoteAddress(address); | |||
// ディスカバリ開始 | |||
discoveryAgent.start(QBluetoothServiceDiscoveryAgent::FullDiscovery); | |||
</syntaxhighlight> | |||
<br> | |||
==== サービスの発見時 ==== | |||
<code>QBluetoothServiceDiscoveryAgent::serviceDiscovered</code>シグナルで通知された<code>QBluetoothServiceInfo</code>クラスから必要な情報を取得する。<br> | |||
<br> | |||
QBluetoothServiceInfoクラスでは、以下に示す情報が取得できる。<br> | |||
<br> | |||
これらの情報は、Bluetoothデバイスとの接続やサービスの詳細な把握に役立つ。<br> | |||
ただし、全ての情報が必ず使用可能とは限らないため、デバイスやサービスの種類によっては取得できる情報が異なることに注意する。<br> | |||
<br> | |||
* サービスの基本情報 | |||
** serviceDescription() | |||
**: サービスの説明文 | |||
** serviceName() | |||
**: サービス名 | |||
** serviceProvider() | |||
**: サービスプロバイダ名 | |||
** serviceUuid() | |||
**: サービスのUUID | |||
** serviceAvailability() | |||
**: サービスの可用性 (0x00~0xFF) | |||
*: <br> | |||
* プロトコル関連 | |||
** protocolServiceMultiplexer() | |||
**: プロトコルサービス多重化子 (PSM) 値 | |||
** serverChannel() | |||
**: RFCOMMサーバチャンネル番号 | |||
** socketProtocol() | |||
**: 使用されているソケットプロトコル (RFCOMM / L2CAP) | |||
*: <br> | |||
* サービスクラス情報 | |||
** serviceClassUuids() | |||
**: サービスクラスのUUIDリスト | |||
** serviceProvider() | |||
**: サービスプロバイダ情報 | |||
*: <br> | |||
* 接続関連 | |||
** device() | |||
**: サービスを提供しているデバイス情報 | |||
** isComplete() | |||
**: サービス情報が完全かどうか | |||
** isRegistered() | |||
**: サービスが登録されているかどうか | |||
** isValid() | |||
**: サービス情報が有効かどうか | |||
*: <br> | |||
* 属性関連 | |||
** attributes() | |||
**: 全ての属性のリスト | |||
** contains(quint16 attributeId) | |||
**: 特定の属性の存在確認 | |||
** attribute(quint16 attributeId) | |||
**: 特定の属性値の取得 | |||
*: <br> | |||
* プロファイル関連 | |||
** majorServiceClass() | |||
**: メジャーサービスクラス (オーディオ、電話等) | |||
** minorServiceClass() | |||
**: マイナーサービスクラス (詳細なサービス種別) | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
connect(&discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, [](const QBluetoothServiceInfo &info) { | |||
// サービス名を取得 | |||
QString name = info.serviceName(); | |||
// UUIDを取得 | |||
QBluetoothUuid uuid = info.serviceUuid(); | |||
// プロトコルを取得 | |||
int protocol = info.protocolServiceMultiplexer(); | |||
qDebug() << "サービス名: " << name; | |||
qDebug() << "UUID: " << uuid.toString(); | |||
qDebug() << "プロトコル: " << protocol; | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
==== 探索完了 または エラー時 ==== | |||
<code>QBluetoothServiceDiscoveryAgent::finished</code>シグナルで探索完了を検知する。<br> | |||
<br> | |||
<code>QBluetoothServiceDiscoveryAgent::error</code>シグナルでエラーを検知する。<br> | |||
<br> | |||
必要に応じて、<code>QBluetoothServiceDiscoveryAgent::stop</code>メソッドで探索を終了することも可能である。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// 完了時の処理 | |||
connect(&discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, []() { | |||
qDebug() << "探索が完了しました"; | |||
}); | |||
// エラー時の処理 | |||
connect(&discoveryAgent, &QBluetoothServiceDiscoveryAgent::error, [](QBluetoothServiceDiscoveryAgent::Error error) { | |||
switch (error) { | |||
case QBluetoothServiceDiscoveryAgent::NoError: | |||
qDebug() << "エラーなし"; | |||
break; | |||
case QBluetoothServiceDiscoveryAgent::PoweredOffError: | |||
qDebug() << "Bluetoothがオフです"; | |||
break; | |||
default: | |||
qDebug() << "その他のエラー"; | |||
} | |||
}); | |||
// 探索を途中で停止する場合 | |||
discoveryAgent.stop(); | |||
</syntaxhighlight> | |||
<br> | |||
==== 組み合わせ ==== | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
#include <QBluetoothServiceDiscoveryAgent> | #include <QBluetoothServiceDiscoveryAgent> | ||
#include <QBluetoothAddress> | #include <QBluetoothAddress> | ||
#include <QDebug> | #include <QDebug> | ||
class ServiceDiscovery : public QObject | class ServiceDiscovery : public QObject | ||
| 393行目: | 547行目: | ||
private: | private: | ||
QBluetoothServiceDiscoveryAgent discoveryAgent; | |||
// | // プロトコルタイプ | ||
QString protocolToString(int protocol) | QString protocolToString(int protocol) | ||
{ | { | ||
| 407行目: | 561行目: | ||
} | } | ||
// | // エラーコード | ||
QString errorToString(QBluetoothServiceDiscoveryAgent::Error error) | QString errorToString(QBluetoothServiceDiscoveryAgent::Error error) | ||
{ | { | ||
| 421行目: | 575行目: | ||
public: | public: | ||
explicit ServiceDiscovery(QObject* parent = nullptr) : QObject(parent) | explicit ServiceDiscovery(QObject* parent = nullptr) : QObject(parent), discoveryAgent(this) | ||
{ | { | ||
// 各種シグナルとスロットの接続 | |||
connect(&discoveryAgent, &QBluetoothServiceDiscoveryAgent::serviceDiscovered, this, &ServiceDiscovery::onServiceDiscovered); | |||
connect(&discoveryAgent, &QBluetoothServiceDiscoveryAgent::finished, this, &ServiceDiscovery::onScanFinished); | |||
connect(&discoveryAgent, static_cast<void(QBluetoothServiceDiscoveryAgent::*)(QBluetoothServiceDiscoveryAgent::Error)>(&QBluetoothServiceDiscoveryAgent::error), | |||
this, &ServiceDiscovery::onError); | |||
} | } | ||
| 442行目: | 587行目: | ||
void startDiscovery(const QBluetoothAddress& address) | void startDiscovery(const QBluetoothAddress& address) | ||
{ | { | ||
qDebug() << "サービス探索を開始..."; | |||
discoveryAgent.setRemoteAddress(address); | |||
discoveryAgent.start(QBluetoothServiceDiscoveryAgent::FullDiscovery); | |||
} | } | ||
| 456行目: | 595行目: | ||
void stopDiscovery() | void stopDiscovery() | ||
{ | { | ||
qDebug() << "サービス探索を停止..."; | |||
discoveryAgent.stop(); | |||
} | } | ||
private slots: | private slots: | ||
// | // サービスの探索に成功した場合 | ||
void onServiceDiscovered(const QBluetoothServiceInfo& service) | void onServiceDiscovered(const QBluetoothServiceInfo& service) | ||
{ | { | ||
| 476行目: | 609行目: | ||
// サービスの詳細情報を表示 | // サービスの詳細情報を表示 | ||
if (service.serviceUuid().isNull()) | if (service.serviceUuid().isNull()) qDebug() << " UUID: カスタムUUID"; | ||
else qDebug() << " UUID: " << service.serviceUuid().toString(); | |||
else | // サービスクラスを表示 | ||
QList<QBluetoothUuid> serviceClasses = service.serviceClassUuids(); | |||
if (!serviceClasses.isEmpty()) { | |||
qDebug() << " サービスクラス:"; | |||
for (const QBluetoothUuid& uuid : serviceClasses) { | |||
qDebug() << " -" << uuid.toString(); | |||
} | |||
} | } | ||
| 493行目: | 631行目: | ||
} | } | ||
// | // 探索完了時 | ||
void onScanFinished() | void onScanFinished() | ||
{ | { | ||
| 499行目: | 637行目: | ||
} | } | ||
// | // エラー発生時 | ||
void onError(QBluetoothServiceDiscoveryAgent::Error error) | void onError(QBluetoothServiceDiscoveryAgent::Error error) | ||
{ | { | ||
| 505行目: | 643行目: | ||
} | } | ||
}; | }; | ||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// 使用方法 | |||
ServiceDiscovery discovery; | |||
// 例: MACアドレスを指定してサービス探索を開始 | |||
QBluetoothAddress address("XX:XX:XX:XX:XX:XX"); | |||
discovery.startDiscovery(address); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
<br><br> | <br><br> | ||
| 518行目: | 666行目: | ||
* 1度ペアリングされたデバイスは、特別な設定がない限り、自動的に再接続可能になる。 | * 1度ペアリングされたデバイスは、特別な設定がない限り、自動的に再接続可能になる。 | ||
<br> | <br> | ||
==== ペアリングの準備 ==== | |||
<code>QBluetoothLocalDevice</code>クラスのインスタンスを生成して、ローカルのBluetoothアダプタを初期化する。<br> | |||
<br> | |||
以下に示すペアリング関連のシグナルに対するスロットを接続する。<br> | |||
* QBluetoothLocalDevice::pairingFinished | |||
* QBluetoothLocalDevice::pairingDisplayConfirmation | |||
* QBluetoothLocalDevice::pairingDisplayPinCode | |||
* QBluetoothLocalDevice::error | |||
<br> | |||
これらの処理は非同期で行われており、シグナル / スロットメカニズムを通じて状態の変更が通知される。<br> | |||
そのため、ユーザインターフェースと組み合わせる場合は、各シグナルに応じて適切なUIの更新を行う必要がある。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
#include <QBluetoothLocalDevice> | |||
#include <QDebug> | |||
QBluetoothLocalDevice localDevice; | |||
// シグナルとスロットの接続 | |||
connect(&localDevice, &QBluetoothLocalDevice::pairingFinished, [](const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing status) { | |||
qDebug() << "ペアリング完了"; | |||
}); | |||
connect(&localDevice, &QBluetoothLocalDevice::pairingDisplayConfirmation, [](const QBluetoothAddress &address, QString pin) { | |||
qDebug() << "ペアリング確認:" << pin; | |||
}); | |||
connect(&localDevice, &QBluetoothLocalDevice::pairingDisplayPinCode, [](const QBluetoothAddress &address, QString pin) { | |||
qDebug() << "PINコード:" << pin; | |||
}); | |||
connect(&localDevice, &QBluetoothLocalDevice::error, []() { | |||
qDebug() << "エラー発生"; | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
==== ペアリング要求 ==== | |||
リモートデバイスのBluetoothアドレス (QBluetoothAddressクラス) を指定して、<code>QBluetoothLocalDevice::requestPairing</code>メソッドを実行する。<br> | |||
この時、ペアリングモードとして<code>QBluetoothLocalDevice::Paired</code>を指定する。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
#include <QBluetoothAddress> | |||
// デバイスのBluetoothアドレスを設定 | |||
QBluetoothAddress address("XX:XX:XX:XX:XX:XX"); | |||
// ペアリング開始 | |||
localDevice.requestPairing(address, QBluetoothLocalDevice::Paired); | |||
</syntaxhighlight> | |||
<br> | |||
==== ペアリング処理中 ==== | |||
Bluetoothデバイスによっては、PINコードの表示や確認が必要になる。<br> | |||
<br> | |||
<code>QBluetoothLocalDevice::pairingDisplayPinCode</code>シグナルを受信した場合、ユーザにPINコードを表示する。<br> | |||
<br> | |||
<code>QBluetoothLocalDevice::pairingDisplayConfirmation</code>シグナルを受信した場合は、ユーザに確認を求めて、<code>QBluetoothLocalDevice::pairingConfirmation</code>メソッドで応答する。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// ペアリング確認に応答 | |||
localDevice.pairingConfirmation(true); // 承認する場合 | |||
localDevice.pairingConfirmation(false); // 拒否する場合 | |||
</syntaxhighlight> | |||
<br> | |||
==== ペアリング完了 ==== | |||
<code>QBluetoothLocalDevice::pairingFinished</code>シグナルを受信して処理結果を確認する。<br> | |||
<br> | |||
エラーが発生した場合は、<code>QBluetoothLocalDevice::error</code>シグナルを受信する。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// ペアリング結果の確認 | |||
#include <QBluetoothLocalDevice> | |||
#include <QDebug> | |||
// ペアリング完了シグナルの処理 | |||
connect(&localDevice, &QBluetoothLocalDevice::pairingFinished, [](const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing status) { | |||
switch (status) { | |||
case QBluetoothLocalDevice::Paired: | |||
qDebug() << "ペアリング成功:" << address.toString(); | |||
break; | |||
case QBluetoothLocalDevice::Unpaired: | |||
qDebug() << "ペアリング解除:" << address.toString(); | |||
break; | |||
default: | |||
qDebug() << "不明な状態:" << address.toString(); | |||
break; | |||
} | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// エラーの確認 | |||
// QBluetoothLocalDevice::errorシグナルを受信してエラー発生を検知する | |||
// エラーシグナルの処理 | |||
connect(&localDevice, &QBluetoothLocalDevice::error, []() { | |||
qDebug() << "ペアリングでエラーが発生しました"; | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
==== ペアリング管理 ==== | |||
<code>QBluetoothLocalDevice::connectedDevices</code>メソッドを実行して、ペアリング済みデバイスの一覧を取得することが可能である。<br> | |||
また、<code>QBluetoothLocalDevice::pairingStatus</code>メソッドを実行して、特定デバイスのペアリング状態を確認できる。<br> | |||
<br> | |||
ペアリングを解除する場合は、ペアリングモードを<code>QBluetoothLocalDevice::Unpaired</code>に指定して<code>QBluetoothLocalDevice::requestPairing</code>メソッドを実行する。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// ペアリング状態の確認 | |||
QBluetoothLocalDevice::Pairing status = localDevice.pairingStatus(address); | |||
// ペアリング済みデバイスの取得 | |||
QList<QBluetoothAddress> devices = localDevice.connectedDevices(); | |||
</syntaxhighlight> | |||
<br> | |||
==== 組み合わせ ==== | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
#include <QBluetoothLocalDevice> | #include <QBluetoothLocalDevice> | ||
#include <QDebug> | #include <QDebug> | ||
class PairingManager : public QObject | class PairingManager : public QObject | ||
| 528行目: | 790行目: | ||
private: | private: | ||
QBluetoothLocalDevice localDevice; | |||
// | // ペアリング状態 | ||
QString pairingStatusToString(QBluetoothLocalDevice::Pairing status) | QString pairingStatusToString(QBluetoothLocalDevice::Pairing status) | ||
{ | { | ||
| 542行目: | 804行目: | ||
public: | public: | ||
explicit PairingManager(QObject* parent = nullptr) : QObject(parent) | explicit PairingManager(QObject *parent = nullptr) : QObject(parent), localDevice(this) | ||
{ | { | ||
// 各種シグナルとスロットの接続 | |||
connect(&localDevice, &QBluetoothLocalDevice::pairingFinished, this, &PairingManager::onPairingFinished); | |||
connect(&localDevice, &QBluetoothLocalDevice::error, this, &PairingManager::onError); | |||
connect(&localDevice, &QBluetoothLocalDevice::pairingDisplayConfirmation, this, &PairingManager::onPairingConfirmationRequest); | |||
connect(&localDevice, &QBluetoothLocalDevice::pairingDisplayPinCode, this, &PairingManager::onPairingDisplayPinCode); | |||
} | } | ||
| 563行目: | 816行目: | ||
void requestPairing(const QBluetoothAddress& address) | void requestPairing(const QBluetoothAddress& address) | ||
{ | { | ||
qDebug() << "ペアリングを開始..." << address.toString(); | |||
localDevice.requestPairing(address, QBluetoothLocalDevice::Paired); | |||
} | } | ||
| 576行目: | 823行目: | ||
void removePairing(const QBluetoothAddress& address) | void removePairing(const QBluetoothAddress& address) | ||
{ | { | ||
qDebug() << "ペアリングを解除..." << address.toString(); | |||
localDevice.requestPairing(address, QBluetoothLocalDevice::Unpaired); | |||
} | } | ||
| 589行目: | 830行目: | ||
QBluetoothLocalDevice::Pairing getPairingStatus(const QBluetoothAddress &address) | QBluetoothLocalDevice::Pairing getPairingStatus(const QBluetoothAddress &address) | ||
{ | { | ||
return localDevice.pairingStatus(address); | |||
} | } | ||
| 601行目: | 836行目: | ||
QList<QBluetoothAddress> getPairedDevices() | QList<QBluetoothAddress> getPairedDevices() | ||
{ | { | ||
return localDevice.connectedDevices(); | |||
} | } | ||
private slots: | private slots: | ||
// | // ペアリング完了時 | ||
void onPairingFinished(const QBluetoothAddress& address, QBluetoothLocalDevice::Pairing status) | void onPairingFinished(const QBluetoothAddress& address, QBluetoothLocalDevice::Pairing status) | ||
{ | { | ||
| 619行目: | 848行目: | ||
} | } | ||
// | // エラー発生時 | ||
void onError() | void onError() | ||
{ | { | ||
| 625行目: | 854行目: | ||
} | } | ||
// | // ペアリング確認要求時 | ||
void onPairingConfirmationRequest(const QBluetoothAddress& address, QString pin) | void onPairingConfirmationRequest(const QBluetoothAddress& address, QString pin) | ||
{ | { | ||
| 634行目: | 863行目: | ||
// ここに、ユーザに確認を求めるUIを表示する | // ここに、ユーザに確認を求めるUIを表示する | ||
// 以下の例では、自動的に確認している | // 以下の例では、自動的に確認している | ||
localDevice | localDevice.pairingConfirmation(true); | ||
} | } | ||
// | // PINコード表示要求時 | ||
void onPairingDisplayPinCode(const QBluetoothAddress &address, QString pin) | void onPairingDisplayPinCode(const QBluetoothAddress &address, QString pin) | ||
{ | { | ||
| 664行目: | 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> | |||
<syntaxhighlight lang="c++"> | |||
#include <QBluetoothSocket> | |||
#include <QDebug> | |||
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> | <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++"> | <syntaxhighlight lang="c++"> | ||
#include <QBluetoothSocket> | #include <QBluetoothSocket> | ||
#include <QDebug> | #include <QDebug> | ||
class BluetoothConnection : public QObject | class BluetoothConnection : public QObject | ||
| 675行目: | 1,010行目: | ||
private: | private: | ||
QBluetoothSocket socket; | |||
// | // エラーコード | ||
QString errorToString(QBluetoothSocket::SocketError error) | QString errorToString(QBluetoothSocket::SocketError error) | ||
{ | { | ||
| 691行目: | 1,026行目: | ||
} | } | ||
// | // 接続状態 | ||
QString stateToString(QBluetoothSocket::SocketState state) | QString stateToString(QBluetoothSocket::SocketState state) | ||
{ | { | ||
| 706行目: | 1,041行目: | ||
public: | public: | ||
explicit BluetoothConnection(QObject* parent = nullptr) : QObject(parent) | explicit BluetoothConnection(QObject *parent = nullptr) : QObject(parent), socket(QBluetoothServiceInfo::RfcommProtocol, this) | ||
{ | { | ||
// 各種シグナルとスロットの接続 | |||
connect(&socket, &QBluetoothSocket::connected, this, &BluetoothConnection::onConnected); | |||
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() | |||
{ | |||
disconnect(); | |||
} | } | ||
| 728行目: | 1,059行目: | ||
void connectToDevice(const QBluetoothAddress &address, quint16 port) | void connectToDevice(const QBluetoothAddress &address, quint16 port) | ||
{ | { | ||
if (socket.state() == QBluetoothSocket::ConnectedState) { | |||
qDebug() << "既に接続済み"; | |||
return; | |||
} | |||
qDebug() << "デバイスに接続します: " << address.toString(); | |||
qDebug() << "ポート: " << port; | |||
socket.connectToService(address, port); | |||
} | } | ||
| 747行目: | 1,072行目: | ||
void disconnect() | void disconnect() | ||
{ | { | ||
if (socket.state() != QBluetoothSocket::UnconnectedState) { | |||
qDebug() << "接続を切断..."; | |||
socket.disconnectFromService(); | |||
} | } | ||
} | } | ||
| 762行目: | 1,081行目: | ||
bool sendData(const QByteArray &data) | bool sendData(const QByteArray &data) | ||
{ | { | ||
if (socket.state() != QBluetoothSocket::ConnectedState) { | |||
qDebug() << "送信エラー: 接続されていません"; | |||
return false; | |||
} | |||
qint64 bytesWritten = socket.write(data); | |||
if (bytesWritten == -1) { | |||
qDebug() << "送信エラー: データの書き込みに失敗"; | |||
return false; | |||
} | |||
qDebug() << bytesWritten << "バイトデータの送信完了"; | |||
return true; | |||
} | } | ||
private slots: | private slots: | ||
// | // 接続確立時 | ||
void onConnected() | void onConnected() | ||
{ | { | ||
qDebug() << "接続が確立"; | qDebug() << "接続が確立"; | ||
qDebug() << " ローカルアドレス:" << socket | qDebug() << " ローカルアドレス:" << socket.localAddress().toString(); | ||
qDebug() << " リモートアドレス:" << socket | qDebug() << " リモートアドレス:" << socket.peerAddress().toString(); | ||
} | } | ||
// | // 切断時 | ||
void onDisconnected() | void onDisconnected() | ||
{ | { | ||
| 798行目: | 1,111行目: | ||
} | } | ||
// | // エラー発生時 | ||
void onError(QBluetoothSocket::SocketError error) | void onError(QBluetoothSocket::SocketError error) | ||
{ | { | ||
| 804行目: | 1,117行目: | ||
} | } | ||
// | // データ受信時 | ||
void onDataReceived() | void onDataReceived() | ||
{ | { | ||
QByteArray data = socket | QByteArray data = socket.readAll(); | ||
qDebug() << "データを受信: " << data.size() << "バイト"; | qDebug() << "データを受信: " << data.size() << "バイト"; | ||
| 814行目: | 1,127行目: | ||
} | } | ||
// | // 接続状態変更時 | ||
void onStateChanged(QBluetoothSocket::SocketState state) | void onStateChanged(QBluetoothSocket::SocketState state) | ||
{ | { | ||