3. QML realizes Bluetooth communication

1. Description:

In a complex software system, there may be more than one communication protocol, and it may be a combination of multiple communications to realize the entire process of software control. At present, using Bluetooth communication to transmit signals over a short distance is a relatively common way, especially when developing software on the Android side, using Bluetooth communication is very common. This article records a small case of using Bluetooth communication in QML.

2. Implementation steps:

There are two options for using Bluetooth communication in QML. One is to use the three controls BluetoothDiscoveryModel, BluetoothService, and BluetoothSocket that come with quick to implement, or use the three corresponding classes QBluetoothDeviceDiscoveryAgent, QBluetoothLocalDevice, and QBluetoothSocket of qwidget .
At present, the first method seems to be not fully supported by qt. In some cases, there will be bugs, which will make it impossible to connect to Bluetooth devices. The second method is still possible.
Therefore, this article uses QML to build the interface, and the Bluetooth communication function is implemented in Qt using the above three classes.
Show results:
insert image description here

2.1 Class function description:

Premise: Add the Bluetooth module QT += bluetooth*** to the ***.Pro file, and add the following header files to the custom Bluetooth protocol class file:

#include <QBluetoothSocket>		//用于数据通信
#include <QBluetoothLocalDevice>	//用于控制本机蓝牙状态(开启/关闭)
#include <QBluetoothDeviceDiscoveryAgent>	//用于搜寻附近的蓝牙设备
#include <QBluetoothAddress>	//用于提取蓝牙设备的地址

When connecting a Bluetooth device, you need to know the address of the target Bluetooth device. This can be extracted through the information searched by the QBluetoothDeviceDiscoveryAgent class. You also need to know the UUID identification number. Generally, the uuid of the serial port class is used. You can find out what type you use. Search, refer to URL: https://www.jianshu.com/p/eb85cb690e86

2.2 Custom Bluetooth protocol class:

Because in order to call the related functions of Bluetooth configuration in QML, QML and C++ need to interact. You can encapsulate the Bluetooth service module into a separate class, and then use it in the registered QML. For the explanation of the functions in the class, please refer to the code comments. Very detailed. The core code is as follows:
BluetoothProxy.h:

#ifndef BLUETOOTHPROXY_H
#define BLUETOOTHPROXY_H

#include <QObject>

#include <QBluetoothSocket>
#include <QBluetoothLocalDevice>
#include <QBluetoothDeviceDiscoveryAgent>
#include <QBluetoothAddress>


class BluetoothProxy : public QObject
{
    
    
    Q_OBJECT
public:
    explicit BluetoothProxy(QObject *parent = nullptr);
    ~BluetoothProxy();

public slots:

    void addBlueToothDevicesToList(const QBluetoothDeviceInfo&);

    void readBluetoothDataEvent();

    void bluetoothConnectedEvent();

    void bluetoothDisconnectedEvent();

    void onError(QBluetoothSocket::SocketError error);

    //启动搜寻蓝牙
    Q_INVOKABLE void startSearch();
    //发送数据
    Q_INVOKABLE void sendData(QString mData);
    //断开蓝牙
    Q_INVOKABLE void disconnectBth();

signals:
    //每次搜寻到蓝牙设备,发送此信号
    void deviceFind(QString mDeviceInfo);
    //配对状态更新时,发送此信号
    void connectProcess(QString mProcessInfo);


private:
    //用于搜寻附近的蓝牙设备
    QBluetoothDeviceDiscoveryAgent *discoveryAgent;
    //用于控制本机蓝牙状态(开启/关闭)
    QBluetoothLocalDevice *localDevice;
    //用于数据通信
    QBluetoothSocket *socket;

};
#endif // BLUETOOTHPROXY_H

BluetoothProxy.cpp:

#include "bluetoothproxy.h"


//这个UUID要根据自己的使用情况来确定,我使用的是串口类的UUID,具体可https://www.jianshu.com/p/eb85cb690e86
static const QLatin1String serviceUuid("00001101-0000-1000-8000-00805F9B34FB");

BluetoothProxy::BluetoothProxy(QObject *parent) : QObject(parent)
{
    
    
    //在构造函数中初始化一些成员变量
    discoveryAgent = new QBluetoothDeviceDiscoveryAgent();  // 否则搜寻周围的蓝牙设备
    localDevice = new QBluetoothLocalDevice();      // 负责控制设备上的蓝牙(比如开启/关闭等操作)
    socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);   // 负责通信数据传输

    //搜寻到蓝牙设备后,将启动设备信息存储函数
    connect(discoveryAgent,SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),this,SLOT(addBlueToothDevicesToList(QBluetoothDeviceInfo)));

    //接收到有数据传输过来时,将启动读取信息的函数
    connect(socket,SIGNAL(readyRead()),this,SLOT(readBluetoothDataEvent()));

    //与目标设备成功连接够,启动提示函数
    connect(socket,SIGNAL(connected()),this,SLOT(bluetoothConnectedEvent()));

    //与目标设备断开连接时,启动顿开蓝牙提示函数
    connect(socket,SIGNAL(disconnected()),this,SLOT(bluetoothDisconnectedEvent()));

    //出西安错误时,启动错误响应函数
    connect(socket,SIGNAL(error(QBluetoothSocket::SocketError)),this,SLOT(onError(QBluetoothSocket::SocketError)));

}

BluetoothProxy::~BluetoothProxy()
{
    
    

}


void BluetoothProxy::onError(QBluetoothSocket::SocketError error)
{
    
    
    QString str;
    if(QBluetoothSocket::UnknownSocketError == error){
    
    
        str = "UnknownSocketError";
    }else if(QBluetoothSocket::NoSocketError == error){
    
    
        str = "NoSocketError";
    }else if(QBluetoothSocket::HostNotFoundError == error){
    
    
        str = "HostNotFoundError";
    }else if(QBluetoothSocket::ServiceNotFoundError == error){
    
    
        str = "ServiceNotFoundError";
    }else if(QBluetoothSocket::NetworkError == error){
    
    
        str = "NetworkError";
    }else if(QBluetoothSocket::UnsupportedProtocolError == error){
    
    
        str = "UnsupportedProtocolError";
    }else if(QBluetoothSocket::OperationError == error){
    
    
        str = "OperationError";
    }else if(QBluetoothSocket::RemoteHostClosedError == error){
    
    
        str = "RemoteHostClosedError";
    }
    qDebug()<<error;
}

//开始搜寻蓝牙设备
void BluetoothProxy::startSearch()
{
    
    
//    if(localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff){
    
    
//        localDevice->powerOn();//调用打开本地的蓝牙设备
//        discoveryAgent->start();
//    }
    discoveryAgent->start();
}

//发送数据到蓝牙设备
void BluetoothProxy::sendData(QString mData)
{
    
    
    socket->write(mData.toUtf8());
}

//断开蓝牙
void BluetoothProxy::disconnectBth()
{
    
    
    socket->close();
}

//显示蓝牙设备信息
void BluetoothProxy::addBlueToothDevicesToList( const QBluetoothDeviceInfo &info )
{
    
    
    QString deviceInfo = QString("%1 %2").arg(info.address().toString()).arg(info.name());

    qDebug()<<deviceInfo;
    emit deviceFind(deviceInfo);

    //如果发现目标蓝牙,则进行连接
    if(deviceInfo.contains("这里换成自己蓝牙设备的名称")){
    
    

        int index = deviceInfo.indexOf(' ');
        if(index == -1){
    
    
            qDebug()<<"index";
            return;
        }
        //获取目标蓝牙设备地址
        QBluetoothAddress address(deviceInfo.left(index));
        QString name(deviceInfo.mid(index + 1));
        //开始连接
        socket->connectToService(address, QBluetoothUuid(serviceUuid) ,QIODevice::ReadWrite);
        //向qml端发送信号
        emit connectProcess(QString("蓝牙连接中,请稍后....(%1)").arg(name));
    }
}


//接收蓝牙设备发送过来的数据
void BluetoothProxy::readBluetoothDataEvent()
{
    
    
    QByteArray receiceData = socket->readAll();
    if(receiceData.size() > 4)return;

}

void BluetoothProxy::bluetoothConnectedEvent()
{
    
    
    emit connectProcess("蓝牙连接成功....");
}

void BluetoothProxy::bluetoothDisconnectedEvent()
{
    
    
    emit connectProcess("蓝牙已断开....");
}

2.3 Specific use:

Register the above custom class into QML in the main.cpp file :

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include <QQmlContext>

#include "bluetoothproxy.h"


int main(int argc, char *argv[])
{
    
    
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
	
	//自定义蓝牙类注册到QML中
    BluetoothProxy blueTooth;
    engine.rootContext()->setContextProperty("myBlueTooth",&blueTooth);

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
    
    
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

After registering the above custom Bluetooth class in QML, it can be called in the .qml file. The main interface code is as follows:
main.qml:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15


ApplicationWindow {
    
    
    id:root
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Connections{
    
    
        target: myBlueTooth
        function onDeviceFind(mDeviceInfo){
    
    
            blueToothList.append({
    
    info:mDeviceInfo})
        }
        function onConnectProcess(mProcessInfo){
    
    
            popText.text = mProcessInfo
            pop.open()
        }
    }

    Text{
    
    
        id:titleName
        anchors.horizontalCenter: btView.horizontalCenter
        anchors.top: parent.top
        anchors.topMargin: 15
        text: "此处显示蓝牙设备信息"
        font.pixelSize: 20
    }

    ListView{
    
    
        id:btView
        width: 300
        height: 400
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: titleName.bottom
        anchors.topMargin: 15
        spacing: 10
        focus:true
        enabled: true
        highlight: Rectangle {
    
    
            width: parent.width
            height: 20
            color: "lightsteelblue"
            radius: 5
            y: btView.currentItem.y
            Behavior on y {
    
    
                SpringAnimation {
    
    
                    spring: 3
                    damping: 0.2
                }
            }
        }
        model: ListModel{
    
    
            id:blueToothList
            //            ListElement{
    
    
            //                info:""
            //            }
        }
        delegate: Rectangle{
    
    
            color: Qt.rgba(0,0,0,0)
            width: parent.width
            height: 20
            anchors.horizontalCenter: parent.horizontalCenter
            Text{
    
    
                id:deviceInfo
                anchors.centerIn: parent
                text: info
                font.pixelSize: 15
                color: "black"
            }
            MouseArea{
    
    
                anchors.fill: parent
                onClicked: {
    
    
                    btView.currentIndex = index
                }
            }
        }

    }

    Button{
    
    
        id:searchBtn
        width: 100
        height: 50
        text: "搜寻蓝牙"
        onClicked: {
    
    
            myBlueTooth.startSearch()
        }
    }
    Button{
    
    
        id:clearBtn
        width: 100
        height: 50
        anchors.top:searchBtn.bottom
        anchors.topMargin: 10
        text:"清空信息"
        onClicked: {
    
    
            blueToothList.clear()
        }
    }
    Button{
    
    
        id:sendBtn
        width: 100
        height: 50
        anchors.top:clearBtn.bottom
        anchors.topMargin: 10
        text:"发送数据"
        onClicked: {
    
    
            myBlueTooth.sendData("1")
        }
    }
    Button{
    
    
        id:discBtn
        width: 100
        height: 50
        anchors.top:sendBtn.bottom
        anchors.topMargin: 10
        text:"断开蓝牙"
        onClicked: {
    
    
            myBlueTooth.disconnectBth()
        }
    }

    Popup{
    
    
        id:pop
        width: 300
        height: 200
        x:(root.width-pop.width)/2
        y:(root.height-pop.height)/2
        //visible: true// the default value is false
        background: Rectangle {
    
    
            anchors.fill: parent
            border.width: 0
            radius: 20
            color: Qt.rgba(0,0,0,0.4)
        }
        contentItem: Rectangle{
    
    
            anchors.fill: parent
            color: Qt.rgba(0,0,0,0.4)
            border.width: 0
            radius: 20
            Text{
    
    
                id:popText
                anchors.centerIn: parent
                font.pixelSize: 20
                color: "white"
            }
            Row{
    
    
                id:btnRow
                anchors.bottom: parent.bottom
                anchors.left: parent.left
                anchors.right: parent.right
                height: 50
                Button{
    
    
                    id:cancelBtn
                    width: 60
                    height: 25
                    anchors.right: parent.right
                    anchors.rightMargin: 15
                    anchors.bottom: parent.bottom
                    anchors.bottomMargin: 15
                    text: "Yes"
                    onClicked: {
    
    
                        pop.close()
                    }
                }
            }
        }
    }

}

The interface design is relatively simple, mainly to realize the function, the interface effect is as follows:
insert image description here

2.4 Functional test:

I downloaded a SPP Bluetooth serial port software on my Android phone, which can be downloaded in the app store of the phone. After opening the software, select the ***+ sign in the upper right corner of the page, and then select the server mode ***, as shown in the figure below Shown:
insert image description here
After starting the server, you can run the Qt program, and then click the search Bluetooth button on the interface to automatically search for nearby Bluetooth devices. Note: change the name of the Bluetooth device in the code to the name of your own device , otherwise you will not be able to connect Bluetooth. If you encounter a situation where Bluetooth cannot be detected, you can click the setting button
in the upper right corner of the Bluetooth assistant on your mobile phone , choose to enable detectability , and pay attention to changing the receiving format of the data to utf-8 , because the data format sent by the Bluetooth terminal in the above code is defined For utf-8 format. As shown in the figure below: Then you can transfer data happily. . . .
insert image description here

Continuously updating, please pay more attention to...

Guess you like

Origin blog.csdn.net/FY_13781298928/article/details/129862306