Qt例子学习笔记 - /Examples/Qt-6.2.0/bluetooth/btscanner

71 篇文章 4 订阅
这段代码展示了如何使用Qt库进行蓝牙设备发现和服务查询。`main.cpp`启动了一个对话框,显示附近蓝牙设备的服务。`service.h`和`service.cpp`定义了一个对话框,用于添加发现的服务到列表。`device.h`和`device.cpp`则负责查找蓝牙设备并提供配对选项。
摘要由CSDN通过智能技术生成

main.cpp

#include "device.h"

#include <QApplication>
#include <QtCore/QLoggingCategory>

int main(int argc, char *argv[])
{
    // QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
    QApplication app(argc, argv);

    DeviceDiscoveryDialog d;
    QObject::connect(&d, SIGNAL(accepted()), &app, SLOT(quit()));
    d.show();

    app.exec();

    return 0;
}

service.h

#ifndef SERVICE_H
#define SERVICE_H

#include "ui_service.h"

#include <QDialog>
//此类以独立于平台和协议的方式保存蓝牙地址。
QT_FORWARD_DECLARE_CLASS(QBluetoothAddress)
//QBluetoothServiceInfo 提供有关蓝牙设备提供的服务的信息。
//此外,它还可以用于在本地设备上注册新服务。
//请注意,此类注册仅影响蓝牙 SDP 条目。
//任何侦听传入连接的服务器(例如 RFCOMM 服务器)都必须在调用 registerService() 之前启动。
//注销必须以相反的顺序进行。
QT_FORWARD_DECLARE_CLASS(QBluetoothServiceInfo)
//发现过程依赖于蓝牙服务发现过程 (SDP)。
//查询所有可接触蓝牙设备提供的服务需要以下步骤:
//创建一个 QBluetoothServiceDiscoveryAgent 实例,
//连接到 serviceDiscovered() 或 finished() 信号,
//并调用 start()。
QT_FORWARD_DECLARE_CLASS(QBluetoothServiceDiscoveryAgent)

QT_USE_NAMESPACE
//对话窗口是一个顶级窗口,主要用于短期任务和与用户的简短交流。
//QDialogs 可以是模态的或非模态的。
//QDialogs 可以提供返回值,并且它们可以具有默认按钮。
//QDialogs 也可以在它们的右下角有一个 QSizeGrip,
//使用 setSizeGripEnabled()。
//请注意,QDialog(以及任何其他类型为 Qt::Dialog 的小部件)使用父小部件与 Qt 中的其他类略有不同。
//对话框始终是顶级小部件,但如果它有父级小部件,则其默认位置位于父级顶级小部件的顶部(如果它本身不是顶级小部件)。
//它还将共享父级的任务栏条目。
//使用 QWidget::setParent() 函数的重载来更改 QDialog 小部件的所有权。
//此函数允许您显式设置重新父控件的窗口标志;
//使用重载函数将清除指定窗口系统属性的窗口标志(特别是它将重置 Qt::Dialog 标志)。
//注意:对话框的父关系并不意味着对话框将始终堆叠在父窗口的顶部。
//为确保对话框始终位于顶部,请将对话框设为模态。
//这也适用于对话框本身的子窗口。
//为确保对话框的子窗口位于对话框的顶部,还应使子窗口成为模态窗口。

//模态对话框
class ServiceDiscoveryDialog : public QDialog
{
    Q_OBJECT

public:
    ServiceDiscoveryDialog(const QString &name, const QBluetoothAddress &address, QWidget *parent = nullptr);
    ~ServiceDiscoveryDialog();

public slots:
    void addService(const QBluetoothServiceInfo&);

private:
    QBluetoothServiceDiscoveryAgent *discoveryAgent;
    Ui_ServiceDiscovery *ui;
};

#endif

service.cpp

#include "service.h"

#include <qbluetoothaddress.h>
#include <qbluetoothservicediscoveryagent.h>
#include <qbluetoothserviceinfo.h>
#include <qbluetoothlocaldevice.h>
#include <qbluetoothuuid.h>


ServiceDiscoveryDialog::ServiceDiscoveryDialog(const QString &name,
                                               const QBluetoothAddress &address, QWidget *parent)
:   QDialog(parent), ui(new Ui_ServiceDiscovery)
{
    ui->setupUi(this);

    //使用默认蓝牙适配器
    //QBluetoothLocalDevice 提供获取和设置本地蓝牙设备状态的函数。
    //在 iOS 和 Windows 上,不能使用这个类,因为平台没有公开任何可能提供本地蓝牙设备信息的数据或 API。
    QBluetoothLocalDevice localDevice;
    //此类以独立于平台和协议的方式保存蓝牙地址。
    QBluetoothAddress adapterAddress = localDevice.address();

    //如果有多个蓝牙适配器,则可以
    //通过提供 MAC 地址来设置将使用哪个适配器。
    //示例代码:
    /*
        QBluetoothAddress adapterAddress("XX:XX:XX:XX:XX:XX")
        discoveryAgent = new QBluetoothServiceDiscoveryAgent(adapterAddress);
    */
    discoveryAgent = new QBluetoothServiceDiscoveryAgent(adapterAddress);

    discoveryAgent->setRemoteAddress(address);

    setWindowTitle(name);

    connect(discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
            this, SLOT(addService(QBluetoothServiceInfo)));
    connect(discoveryAgent, SIGNAL(finished()), ui->status, SLOT(hide()));

    discoveryAgent->start();
}

ServiceDiscoveryDialog::~ServiceDiscoveryDialog()
{
    delete discoveryAgent;
    delete ui;
}

void ServiceDiscoveryDialog::addService(const QBluetoothServiceInfo &info)
{
    if (info.serviceName().isEmpty())
        return;

    QString line = info.serviceName();
    if (!info.serviceDescription().isEmpty())
        line.append("\n\t" + info.serviceDescription());
    if (!info.serviceProvider().isEmpty())
        line.append("\n\t" + info.serviceProvider());

    ui->list->addItem(line);
}

device.h

#ifndef DEVICE_H
#define DEVICE_H

#include "ui_device.h"

#include <qbluetoothlocaldevice.h>

#include <QDialog>
//发现附近的蓝牙设备:
//创建一个 QBluetoothDeviceDiscoveryAgent 实例,
//连接到 deviceDiscovered() 或 finished() 信号,
//并调用 start()。
/*
    void MyClass::startDeviceDiscovery()
    {
        //Create a discovery agent and connect to its signals
        QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
        connect(discoveryAgent,SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
                this,SLOT(deviceDiscovered(QBluetoothDeviceInfo)));

        //Start a discovery
        discoveryAgent->start();
        //...
    }  
    //In your local slot,read information about the found devices
    void MyClass::deviceDiscovered(const QBluetoothDeviceInfo &device)
    {
        qDebug()<<"Found new device: "<<device.name()<<'('<<device.address().toString()<<')';
    }
    //要异步检索结果,请连接到 deviceDiscovered() 信号。
    //要获取所有已发现设备的列表,请在finished() 信号后调用 foundDevices()。
*/
//此类可用于发现经典和低功耗蓝牙设备。
//可以通过 QBluetoothDeviceInfo::coreConfigurations() 属性确定单个设备类型。
//在大多数情况下,discoveredDevices() 返回的列表包含这两种类型的设备。
//然而,并非每个平台都能检测到这两种类型的设备。
//在具有此限制的平台上(例如 iOS 仅支持低能耗发现),发现过程会将搜索限制为支持的类型。
QT_FORWARD_DECLARE_CLASS(QBluetoothDeviceDiscoveryAgent)
QT_FORWARD_DECLARE_CLASS(QBluetoothDeviceInfo)

QT_USE_NAMESPACE

class DeviceDiscoveryDialog : public QDialog
{
    Q_OBJECT

public:
    DeviceDiscoveryDialog(QWidget *parent = nullptr);
    ~DeviceDiscoveryDialog();

public slots:
    void addDevice(const QBluetoothDeviceInfo&);
    void on_power_clicked(bool clicked);
    void on_discoverable_clicked(bool clicked);
    void displayPairingMenu(const QPoint &pos);
    void pairingDone(const QBluetoothAddress&, QBluetoothLocalDevice::Pairing);
private slots:
    void startScan();
    void scanFinished();
    void itemActivated(QListWidgetItem *item);
    void hostModeStateChanged(QBluetoothLocalDevice::HostMode);

private:
    QBluetoothDeviceDiscoveryAgent *discoveryAgent;
    QBluetoothLocalDevice *localDevice;
    Ui_DeviceDiscovery *ui;
};

#endif

device.cpp

#include "device.h"
#include "service.h"

#include <qbluetoothaddress.h>
#include <qbluetoothdevicediscoveryagent.h>
#include <qbluetoothlocaldevice.h>
#include <QMenu>
#include <QDebug>

DeviceDiscoveryDialog::DeviceDiscoveryDialog(QWidget *parent)
:   QDialog(parent), localDevice(new QBluetoothLocalDevice),
    ui(new Ui_DeviceDiscovery)
{
    ui->setupUi(this);


    discoveryAgent = new QBluetoothDeviceDiscoveryAgent();

    connect(ui->scan, SIGNAL(clicked()), this, SLOT(startScan()));

    connect(discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
            this, SLOT(addDevice(QBluetoothDeviceInfo)));
    connect(discoveryAgent, SIGNAL(finished()), this, SLOT(scanFinished()));

    connect(ui->list, SIGNAL(itemActivated(QListWidgetItem*)),
            this, SLOT(itemActivated(QListWidgetItem*)));

    connect(localDevice, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)),
            this, SLOT(hostModeStateChanged(QBluetoothLocalDevice::HostMode)));

    hostModeStateChanged(localDevice->hostMode());
    // add context menu for devices to be able to pair device
    ui->list->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->list, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(displayPairingMenu(QPoint)));
    connect(localDevice, SIGNAL(pairingFinished(QBluetoothAddress,QBluetoothLocalDevice::Pairing))
        , this, SLOT(pairingDone(QBluetoothAddress,QBluetoothLocalDevice::Pairing)));

}

DeviceDiscoveryDialog::~DeviceDiscoveryDialog()
{
    delete discoveryAgent;
}

void DeviceDiscoveryDialog::addDevice(const QBluetoothDeviceInfo &info)
{
    QString label = QString("%1 %2").arg(info.address().toString()).arg(info.name());
    QList<QListWidgetItem *> items = ui->list->findItems(label, Qt::MatchExactly);
    if (items.empty()) {
        QListWidgetItem *item = new QListWidgetItem(label);
        QBluetoothLocalDevice::Pairing pairingStatus = localDevice->pairingStatus(info.address());
        if (pairingStatus == QBluetoothLocalDevice::Paired || pairingStatus == QBluetoothLocalDevice::AuthorizedPaired )
            item->setForeground(QColor(Qt::green));
        else
            item->setForeground(QColor(Qt::black));

        ui->list->addItem(item);
    }

}

void DeviceDiscoveryDialog::startScan()
{
    discoveryAgent->start();
    ui->scan->setEnabled(false);
}

void DeviceDiscoveryDialog::scanFinished()
{
    ui->scan->setEnabled(true);
}

void DeviceDiscoveryDialog::itemActivated(QListWidgetItem *item)
{
    QString text = item->text();

    int index = text.indexOf(' ');

    if (index == -1)
        return;

    QBluetoothAddress address(text.left(index));
    QString name(text.mid(index + 1));

    ServiceDiscoveryDialog d(name, address);
    d.exec();
}

void DeviceDiscoveryDialog::on_discoverable_clicked(bool clicked)
{
    if (clicked)
        localDevice->setHostMode(QBluetoothLocalDevice::HostDiscoverable);
    else
        localDevice->setHostMode(QBluetoothLocalDevice::HostConnectable);
}

void DeviceDiscoveryDialog::on_power_clicked(bool clicked)
{
    if (clicked)
        localDevice->powerOn();
    else
        localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);
}

void DeviceDiscoveryDialog::hostModeStateChanged(QBluetoothLocalDevice::HostMode mode)
{
    if (mode != QBluetoothLocalDevice::HostPoweredOff)
        ui->power->setChecked(true);
    else
       ui->power->setChecked( false);

    if (mode == QBluetoothLocalDevice::HostDiscoverable)
        ui->discoverable->setChecked(true);
    else
        ui->discoverable->setChecked(false);

    bool on = !(mode == QBluetoothLocalDevice::HostPoweredOff);


    ui->scan->setEnabled(on);
    ui->discoverable->setEnabled(on);
}
void DeviceDiscoveryDialog::displayPairingMenu(const QPoint &pos)
{
    if (ui->list->count() == 0)
        return;
    QMenu menu(this);
    QAction *pairAction = menu.addAction("Pair");
    QAction *removePairAction = menu.addAction("Remove Pairing");
    QAction *chosenAction = menu.exec(ui->list->viewport()->mapToGlobal(pos));
    QListWidgetItem *currentItem = ui->list->currentItem();

    QString text = currentItem->text();
    int index = text.indexOf(' ');
    if (index == -1)
        return;

    QBluetoothAddress address (text.left(index));
    if (chosenAction == pairAction) {
        localDevice->requestPairing(address, QBluetoothLocalDevice::Paired);
    } else if (chosenAction == removePairAction) {
        localDevice->requestPairing(address, QBluetoothLocalDevice::Unpaired);
    }
}
void DeviceDiscoveryDialog::pairingDone(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)
{
    QList<QListWidgetItem *> items = ui->list->findItems(address.toString(), Qt::MatchContains);

    if (pairing == QBluetoothLocalDevice::Paired || pairing == QBluetoothLocalDevice::AuthorizedPaired ) {
        for (int var = 0; var < items.count(); ++var) {
            QListWidgetItem *item = items.at(var);
            item->setForeground(QColor(Qt::green));
        }
    } else {
        for (int var = 0; var < items.count(); ++var) {
            QListWidgetItem *item = items.at(var);
            item->setForeground(QColor(Qt::red));
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值