Bluetooth クライアントの使用 QBluetoothSocket—Qt For Android

Bluetooth について学ぶ

Bluetooth クラシックと Bluetooth Low Energy の違い

クラシック Bluetooth (Bluetooth Classic) : 2.4 GHz (ISM) 周波数帯域で、基本レート/拡張データ レート (BR/EDR)、79 チャネルに分割されます。ポイントツーポイントのデバイス通信をサポートし、主にワイヤレス オーディオ ストリーミングを可能にするために使用され、ワイヤレス スピーカー、ヘッドフォン、車載エンターテイメント システムの背後にある標準の無線プロトコルとなっています。Bluetooth Classic は、モバイル印刷などのデータ転送プログラムもサポートしています。

Bluetooth Low Energy : 低電力動作向けに設計されています。2.4GHz のライセンス不要の ISM 帯域で動作し、合計 40 チャネルでデータを送信します。Bluetooth LE は、ポイントツーポイント、ブロードキャスト、メッシュなどの複数の通信トポロジをサポートします。Bluetooth を有効にして、信頼性の高い大規模ネットワークの構築をサポートします。LE は、高精度屋内測位サービスのニーズを満たすデバイス測位技術にも広く使用されています。

クラシック Bluetooth と Bluetooth Low Energy の違い - Zhihu

Bluetooth のペアリングと接続確立のプロセス

taodudu.cc/news/show-3161112.html?action=onClick

Qt Bluetooth モジュール

サポートされているプラ​​ットフォーム

 Qt 5.14 では、Windows 7 以降ではクラシック Bluetooth、Windows 8 以降では Bluetooth LE をサポートするネイティブ Win32 ポートが追加されています。これは、構成オプション -native-win32-bluetooth によってビルド時に有効にする必要があります。このオプションが設定されておらず、Win32 ターゲット プラットフォームが必要な UWP API をサポートしている場合、UWP バックエンドが既定で使用されます (最小要件は Windows 10 バージョン 1507 で、Windows 10 バージョン 1607 以降はサービス検出が若干改善されています)。

使用

環境

バージョン: Qt15.15.2

言語: C++

プラットフォーム: Android 11

Bluetoothタイプ:クラシックBluetooth(Bluetoothクラシック)

コードと手順

使用前にBluetoothモジュールをproファイルにロードしてください

QT += bluetooth

誰もがBluetoothを使用した経験があると思いますが、大まかな手順としては、Bluetoothの状態確認(オンかどうか)→近くのデバイスを探す→ペアリング→接続→データ送信という流れに沿ってコードを紹介していきます。

  • Bluetooth ステータスを確認します (オンになっているかどうか)。

QBluetoothLocalDevice は、ローカル Bluetooth デバイスのステータスを取得および設定する機能を提供します。 

アクセス可能な

QBluetoothLocalDevice::HostMode QBluetoothLocalDevice::hostMode() const

現在のホストのモードを取得するには、ここではオンになっているかどうかだけを判断します。オンになっていない場合は、powerOn() を使用して Bluetooth をオンにすることができます。ただし、呼び出した後、すぐに接続を作成するために呼び出します。失敗する可能性があり、ハードウェアの準備がまだ整っていない可能性があります。

   QBluetoothLocalDevice* m_pLocalDev;
   m_pLocalDev = new QBluetoothLocalDevice(this);

   //检查蓝牙是否未打开
   if(m_pLocalDev->hostMode()==QBluetoothLocalDevice::HostPoweredOff)
    {
        m_pLocalDev->powerOn(); //打开蓝牙
        emit errorBTDevPowerOff();
        return false;
    }

  •  近くの Bluetooth デバイスを探す

 QBluetoothDeviceDiscoveryAgentクラスは近くの Bluetooth デバイスを検出します

void BluetoothDevice::BluetoothDevice()
{
    ...
   //初始化

    QBluetoothDeviceDiscoveryAgent* m_pDevDiscoveryAgent;
    m_pDevDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);


    connect(m_pDevDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,     this, &BluetoothDevice::onDeviceDiscovered);
    connect(m_pDevDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &BluetoothDevice::onDiscoverFinished);
    connect(m_pDevDiscoveryAgent, QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error),
            this, &BluetoothDevice::onDiscoverFinished);

   ...
}


void BluetoothDevice::refreshBTDevices()
{
    ...
    //开始查找附近蓝牙设备,根据需求这里限定为经典蓝牙
    m_pDevDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::ClassicMethod);

}

//查找到的蓝牙设备的信息
void BluetoothDevice::onDeviceDiscovered(const QBluetoothDeviceInfo &device)
{
    //MAC地址
    const QString& macAddr = device.address().toString();
    //设备名称
    const QString& name= device.name();

   //判读检测到设备是否与本地设备配对
    bool isPaired = false;
   if (pairingStatus == QBluetoothLocalDevice::Paired || pairingStatus == 
    QBluetoothLocalDevice::AuthorizedPaired )
       isPaired =true;
   
} 
//查找结束
void BluetoothDevice::onDiscoverFinished()
{
    emit discoveryFinished();
}

 上記の方法では、近くにある Bluetooth デバイスをいくつか取得しますが、すべてのデバイスを取得できないことがよくあります。状況は次のようなものです。私の携帯電話は開発対象のデバイス(以下、デバイス)の Bluetooth を見つけることができますが、デバイスは携帯電話の Bluetooth を見つけられないため、携帯電話を使用して積極的に開発します。ペアリングを開始すると、ペアリングが成功し、ファイルや情報を送受信できるようになります。ペアリングが成功すると、デバイスは私の電話機の名前と Bluetooth MAC アドレスを認識できるようになりますが、QBluetoothDeviceDiscoveryAgent クラスはまだ私の電話機を見つけることができません。

デバイスは見つかりますが、Qt では見つからないため、Java のメソッドを使用して、ペアになっているデバイスのリストを直接取得してみてください。この方法は可能です。

package org.qtproject.toolkit.bluetooth;

import android.bluetooth.*;

import java.util.ArrayList;
import java.util.Set;
import java.lang.String;

public class BluetoothInfo
{

    public BluetoothInfo(){}
    public  String[] getBondedDevices(boolean isBLE)
    {
        BluetoothAdapter BTAdapter = BluetoothAdapter.getDefaultAdapter();
        Set<BluetoothDevice> bondedDevice = BTAdapter.getBondedDevices();
        ArrayList<String> list = new ArrayList<String>();
        for (BluetoothDevice bt : bondedDevice)
        {
            int deviceType = bt.getType();
            if (!isBLE && (deviceType == BluetoothDevice.DEVICE_TYPE_CLASSIC || deviceType == BluetoothDevice.DEVICE_TYPE_DUAL))
                list.add(bt.getAddress() + " " + bt.getName());
            else if (isBLE && (deviceType == BluetoothDevice.DEVICE_TYPE_LE || deviceType == BluetoothDevice.DEVICE_TYPE_DUAL))
                list.add(bt.getAddress() + " " + bt.getName());
        }
        String[] result = (String[]) list.toArray(new String[list.size()]);
        return result;
    }
};

C++で呼び出される

#ifdef Q_OS_ANDROID
void BluetoothDevice::getBondedTarget()
{
    QAndroidJniEnvironment env;
    QtAndroid::PermissionResult r = QtAndroid::checkPermission("android.permission.ACCESS_FINE_LOCATION");
    if(r == QtAndroid::PermissionResult::Denied)
    {
        QtAndroid::requestPermissionsSync(QStringList() << "android.permission.ACCESS_FINE_LOCATION");
        r = QtAndroid::checkPermission("android.permission.ACCESS_FINE_LOCATION");
        if(r == QtAndroid::PermissionResult::Denied)
        {
            qDebug() << "failed to request";
        }
    }
    qDebug() << "has permission";
    QAndroidJniObject javaClass("org.qtproject.toolkit.bluetooth/BluetoothInfo");

    QAndroidJniObject array = javaClass.callObjectMethod("getBondedDevices", "(Z)[Ljava/lang/String;", false);
    int arraylen = env->GetArrayLength(array.object<jarray>());
    qDebug() << "arraylen:" << arraylen ;

    m_bondedDevices.clear();

    for(int i = 0; i < arraylen; i++)
    {
        QString info = QAndroidJniObject::fromLocalRef(env->GetObjectArrayElement(array.object<jobjectArray>(), i)).toString();
        BTDeviceInfo devInfo;
        devInfo.macAddr = info.left(info.indexOf(' '));
        devInfo.name = info.right(info.length() - info.indexOf(' ') - 1);
        devInfo.isPaired = true;

        m_bondedDevices.append(devInfo);
    }

}
#endif

  •  ペア

上記で、近くにある Bluetooth デバイスのペアリング状態を取得しました。ペアリングされている場合は、手動でペアリングするか、次の方法を試してください。ただし、テスト中、携帯電話の Bluetooth デバイスが見つからなかったので、ペアリングしましたペアリングを要求するコードを試行せずに手動で実行します。

void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing ペアリング)

  • 接続の作成

 Qt は Bluetooth クライアント ( QBluetoothSocket ) と Bluetooth サーバー (QBluetoothServer) をカプセル化します。これは Tcp の使用と非常によく似ています。ソケットはサーバーへの接続を試行し、サーバーは接続を監視し、双方が読み書きできます。

QBluetoothSocket はクライアントとして、サーバーへの接続を要求します。サーバーは、以前にペアリングされた携帯電話またはその他のデバイスです。携帯電話で Bluetooth サーバー QBluetoothServer がオンになっている必要があることに注意してください。オンになっていないと、接続は成功しません。

  • サーバーに接続する

ご覧のとおり、サーバー アドレス、uuid、オープン モードを渡す必要があります。サーバー アドレスは、ペアになっている Bluetooth MAC アドレスです。uuid には多くの値があり、関数ごとに異なる uuid があります。列挙enum QBluetoothUuid::ServiceClassUuidを確認して確認できます。オープニング モードについては言うまでもありません。

void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode = ReadWrite)

コード例

//初始化

QBluetoothSocket* m_pSocket;
QByteArray m_buf;
QString m_strServerUUID;
QString m_strMACAddr;

m_pSocket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol,this);
m_strServerUUID = QBluetoothUuid(QBluetoothUuid::SerialPort).toString();

connect(m_pSocket,&QBluetoothSocket::connected,this,&BluetoothConnection::onConnected);    connect(m_pSocket,&QBluetoothSocket::disconnected,this,&BluetoothConnection::onDisconnect);
connect(m_pSocket,&QBluetoothSocket::readyRead,this,&BluetoothConnection::onReadyRead);
connect(m_pSocket, QOverload<QBluetoothSocket::SocketError>::of(&QBluetoothSocket::error),
            this, &BluetoothConnection::onErrorOccurred);


//连接服务器 (uuid 可传入,可默认)
void BluetoothConnection::connectToSerive(QString strAddr, QString strUuid)
{
    if(m_pSocket->state() == QBluetoothSocket::ConnectedState)
    {
        if(strAddr == m_strMACAddr && strUuid == m_strServerUUID)
        {
            return;
        }
        else
            disconnect();
    }


    if(strUuid != "")
        m_strServerUUID = strUuid;
    m_strMACAddr = strAddr;

    m_pSocket->connectToService(QBluetoothAddress(strAddr), QBluetoothUuid(m_strServerUUID),QIODevice::ReadWrite);
}
  •  データ転送処理

データ送信および処理部分についてはコードは表示されませんが、要件が異なり、コードも異なります。

結論

これはおそらく Android の Bluetooth クライアントの場合に当てはまります。

おすすめ

転載: blog.csdn.net/xiaopei_yan/article/details/130981714