找回密码
 立即注册
Qt开源社区 门户 查看内容

QT软件开发-第十三章 基于QT5蓝牙设备开发 13.1~13.4

2019-5-7 15:11| 发布者: admin| 查看: 8666| 评论: 0

摘要: 点击上方蓝字关注我们蓝牙( Bluetooth® ):是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换(使用2.4—2.485GHz的ISM波段的UHF无线电波)。蓝牙技术最初由电信巨头爱立信公司于 ...


点击上方蓝字关注我们





蓝牙( Bluetooth® ):是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换(使用2.4—2.485GHz的ISM波段的UHF无线电波)。蓝牙技术最初由电信巨头爱立信公司于1994年创制,当时是作为RS232数据线的替代方案。蓝牙可连接多个设备,克服了数据同步的难题。

如今蓝牙由蓝牙技术联盟(Bluetooth SpeciaInterest Group,简称SIG)管理。蓝牙技术联盟在全球拥有超过25,000家成员公司,它们分布在电信、计算机、网络、和消费电子等多重领域。IEEE将蓝牙技术列为IEEE 802.15.1,但如今已不再维持该标准。蓝牙技术联盟负责监督蓝牙规范的开发,管理认证项目,并维护商标权益。制造商的设备必须符合蓝牙技术联盟的标准才能以“蓝牙设备”的名义进入市场。蓝牙技术拥有一套专利网络,可发放给符合标准的设备。



13-0-1图

最新4.0蓝牙开发主要分为经典蓝牙与低功耗蓝牙(BLE)。

BLE是蓝牙低能耗的简称(Bluetooh Low Energy)。蓝牙低能耗(BLE)技术是低成本、短距离、可互操作的鲁棒性无线技术,工作在免许可的2.4GHz ISM射频频段。它从一开始就设计为超低功耗(ULP)无线技术。它利用许多智能手段最大限度地降低功耗。

蓝牙低能耗架构共有两种芯片构成:单模芯片和双模芯片。蓝牙单模芯片可以和其它单模芯片及双模芯片通信,此时后者需要使用自身架构中的蓝牙低能耗技术部分进行收发数据。双模芯片也能与标准蓝牙技术及使用传统蓝牙架构的其它双模芯片通信。

双模芯片可以在目前使用标准蓝牙芯片的任何场合使用。这样安装有双模芯片的手机、PC、个人导航设备(PND)或其它应用就可以和市场上已经在用的所有传统标准蓝牙设备以及所有未来的蓝牙低能耗设备通信。然而,由于这些设备要求执行标准蓝牙和蓝牙低能耗任务,因此双模芯片针对ULP操作的优化程度没有像单模芯片那么高。

QT下经典的蓝牙开发需要用到以下3个类:

QBluetoothDeviceDiscoveryAgent  用于扫描周围蓝牙设备

QBluetoothLocalDevice  用于配置获取设备的蓝牙状态信息等

QBluetoothSocket      用于指进行连接蓝牙设备,读写信息

QT开发蓝牙设备时,需要在pro工程文件中加入: QT+= Bluetooth  代码,否则无法使用蓝牙相关的类。

13.1 扫描获取周围可见的蓝牙设备

13.1.1 QBluetoothDeviceDiscoveryAgent类介绍


QBluetoothDeviceDiscoveryAgent类用于发现附近的蓝牙设备,包括经典蓝牙设备与低功耗蓝牙设备。

使用步骤:

1. new一个QBluetoothDeviceDiscoveryAgent的实例

2. 连接到deviceDiscovered()或finished()信号

3. 并调用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 locaslot, read information about the found devices

void MyClass::deviceDiscovered(const QBluetoothDeviceInfo &device)

{

  qDebug() << "Found new device:" << device.name() << '(' << device.address().toString() << ')';

}

13.1.2 函数介绍

(1) 构造函数


QBluetoothDeviceDiscoveryAgent(QObject *parent = Q_NULLPTR)

QBluetoothDeviceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent = Q_NULLPTR)

示例:

QBluetoothDeviceDiscoveryAgent *discoveryAgent;  //这个是指扫描周围蓝牙设备!

discoveryAgent = new QBluetoothDeviceDiscoveryAgent();

(2) 获取错误信息


Error QBluetoothDeviceDiscoveryAgent::error() const    //返回枚举值

QString QBluetoothDeviceDiscoveryAgent::errorString() const //返回描述错误的字符串

  用于获取发生的错误信息。

  • 错误列表枚举值:

QBluetoothDeviceDiscoveryAgent::NoError

没有发生错误。

QBluetoothDeviceDiscoveryAgent::PoweredOffError

蓝牙适配器断电后,在发现之前将其打开。

QBluetoothDeviceDiscoveryAgent::InputOutputError

从设备写入或读取导致错误。

QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError

传递的本地适配器地址与任何本地蓝牙设备的物理适配器地址都不匹配。

QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError

设备发现不可能在当前平台上实现或实现。 该错误响应于对start()的调用而设置。

QBluetoothDeviceDiscoveryAgent::UnknownError

这种情况的例子是低于5.0的iOS版本,根本不支持蓝牙设备搜索。 这个值是由Qt 5.5引入的。出现未知错误。

(3) 设置扫描设备的类型


QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType() const

void setInquiryType(QBluetoothDeviceDiscoveryAgent::InquiryType type)

类型区别:

QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry

一般的无限制查询。 发现本地附近的所有可见蓝牙设备。

QBluetoothDeviceDiscoveryAgent::LimitedInquiry

有限的查询发现处于有限查询模式的设备。

(4) 判断当前的工作状态


booQBluetoothDeviceDiscoveryAgent::isActive() const

如果当前正在扫描蓝牙设备,则返回true,否则返回false。

(5) 开始与停止槽函数


void QBluetoothDeviceDiscoveryAgent::start()

void QBluetoothDeviceDiscoveryAgent::stop()

Start函数用于启动蓝牙设备设备扫描,stop函数用于停止设备扫描。

(6) 返回已发现的蓝牙列表


QList<QBluetoothDeviceInfo> QBluetoothDeviceDiscoveryAgent::discoveredDevices() const

13.1.3 信号介绍

(1) 停止设备扫描通知信号


void QBluetoothDeviceDiscoveryAgent::canceled()

当调用stop函数时,会调用该信号。用于通知用户,设备已经停止扫描。

(2) 扫描到设备后的通知信号


void QBluetoothDeviceDiscoveryAgent::deviceDiscovered(const QBluetoothDeviceInfo &info)

当调用start函数之后,如果扫描到附近的蓝牙设备,就会发出该信号,通过信号的形参即可获取蓝牙设备的信息。

关联信号示例:

connect(discoveryAgent,

            SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),

            this,

            SLOT(addBlueToothDevicesToList(QBluetoothDeviceInfo))

            );

处理数据示例:

void MainWindow::addBlueToothDevicesToList(const QBluetoothDeviceInfo &info)

{

   // QString labe= QString("%1 %2").arg(info.name()).arg(info.address().toString());

    QString labe= QString("%1 %2").arg(info.address().toString()).arg(info.name());

    ui->comboBox_BluetoothDevice->addItem(label); //添加字符串到comboBox上

}

(3) 设备出现错误通知信号


Error QBluetoothDeviceDiscoveryAgent::error() const

错误的枚举值上面已经介绍。

(4) 蓝牙设备扫描完成通知信号


void QBluetoothDeviceDiscoveryAgent::finished()

当蓝牙设备扫描完成时发出此信号。 如果设备扫描发生错误,则不会发出信号。

13.2 设置本地蓝牙设备

13.2.1 介绍QBluetoothLocalDevice


QBluetoothLocalDevice类允许访问本地蓝牙设备。

QBluetoothLocalDevice类提供获取和设置本地蓝牙设备状态的功能。

比如: 设置本地蓝牙模式、打开本地蓝牙、关闭本地蓝牙等等。

13.2.2函数介绍

(1) 构造函数


QBluetoothLocalDevice(QObject *parent = Q_NULLPTR)

QBluetoothLocalDevice(const QBluetoothAddress &address, QObject *parent = Q_NULLPTR)

示例:

QBluetoothLocalDevice *localDevice;//是指配置获取设备的蓝牙状态信息等!

localDevice = new QBluetoothLocalDevice();

(2) 获取本地蓝牙的MAC地址


QBluetoothAddress QBluetoothLocalDevice::address() const

返回本地蓝牙设备的MAC地址。

注意:在Android上,该设备的本地MAC地址的编程访问被删除。此函数始终以固定值02:00:00:00:00:00作为从Android 6.0开始的本地地址返回。

(3) 返回已经连接的设备列表


QList<QBluetoothAddress> QBluetoothLocalDevice::connectedDevices() const

返回已经连接设备的列表。 该列表与当前配对设备的列表不同。

在Android和OS X上,无法检索连接设备的列表。 只能听取(dis)连接更改。 为了方便起见,这个类监视自实例以来所有的连接和断开事件,并在调用此函数时返回当前列表。 因此,该函数可能在创建实例后不久返回空列表。

(4) 获取与设置蓝牙模式


HostMode QBluetoothLocalDevice::hostMode() const   //获取当前模式

void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode)  //设置模式

本函数用于将本地蓝牙设备的主机模式设置指定模式。

注意:由于受支持平台上的安全策略不同,此方法在各种平台上可能会有不同的行为。 例如,在开启或关闭蓝牙之前,系统可以要求用户确认,并且不支持所有主机模式。 在OS X上,以编程方式更改hostMode()不是可行的。 用户只能在系统偏好设置中打开/关闭蓝牙功能。 有关详细信息,请参阅平台特定的蓝牙文档。

(5) 判断本地蓝牙设备是否可用


booQBluetoothLocalDevice::isValid() const

如果QBluetoothLocalDevice表示可用的本地蓝牙设备,则返回true; 否则返回false。

如果由该类的实例代表的本地蓝牙适配器从系统中移除(例如移除底层蓝牙适配器),则该实例将变为无效。 即使同一蓝牙适配器返回到系统,已经无效的QBluetoothLocalDevice实例仍然无效。

(6) 获取本地蓝牙的名称


QString QBluetoothLocalDevice::name() const

(7) 本地蓝牙的打开与关闭


void QBluetoothLocalDevice::powerOn()

示例:

/*请求打开蓝牙设备*/

localDevice->powerOn();

/*关闭蓝牙设备*/

localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);

  说明: 打开蓝牙与关闭蓝牙并不是一个配对的函数,关闭蓝牙需要设置模式。

(8) 设置获取蓝牙的配对状态


void QBluetoothLocalDevice::requestPairing(const QBluetoothAddress &address, Pairing pairing) //设置

Pairing QBluetoothLocalDevice::pairingStatus(const QBluetoothAddress &address) const  //获取

设置或者获取蓝牙的配对状态。

枚举状态值:

QBluetoothLocalDevice::Unpaired

蓝牙设备未配对。

QBluetoothLocalDevice::Paired

蓝牙设备已配对。 当远程设备启动到本地设备的连接时,系统将提示用户进行授权。

QBluetoothLocalDevice::AuthorizedPaired

蓝牙设备已配对。 当远程设备启动到本地设备的连接时,系统不会提示用户进行授权。

(9) 设置主机模式


void QBluetoothLocalDevice::setHostMode(QBluetoothLocalDevice::HostMode mode)

HostMode QBluetoothLocalDevice::hostMode() const

返回此本地蓝牙设备的当前主机模式。 在OS X上,它是HostPoweredOff或HostConnectable。

模式枚举值:

QBluetoothLocalDevice::HostPoweredOff

关闭设备电源

QBluetoothLocalDevice::HostConnectable

如果远程蓝牙设备先前已与其配对或以其他方式知道其地址,则可以连接到本地蓝牙设备。 如果设备关机,则会启动设备。

QBluetoothLocalDevice::HostDiscoverable

远程蓝牙设备可以发现本地蓝牙设备的存在。 该设备也可以连接并通电。 在Android上,此模式最多只能激活5分钟。

QBluetoothLocalDevice::HostDiscoverableLimitedInquiry

执行有限查询时,远程蓝牙设备可以发现本地蓝牙设备的存在。 这应该用于定位仅在有限的时间段内被发现的服务。此模式在Android上不受支持。 在OS X上,无法将hostMode()设置为HostConnectable或HostPoweredOff。

(10) 配对请求确认


void QBluetoothLocalDevice::pairingConfirmation(booaccept)

   在调用pairingDisplayConfirmation()后获取。 accept参数要么接受配对要么拒绝它。

接受配对始终是指通过requestPairing()发出的最后配对请求。

13.2.3 信号介绍

(1) 设备建立连接信号通知


void QBluetoothLocalDevice::deviceConnected(const QBluetoothAddress &address)

当本地设备建立到具有地址的远程设备连接时,会发出此信号。

(2) 设备断开连接信号通知


void QBluetoothLocalDevice::deviceDisconnected(const QBluetoothAddress &address)

本地设备从具有地址的远程蓝牙设备断开连接时发出此信号。

(3) 设备配对错误信号通知


void QBluetoothLocalDevice::error(QBluetoothLocalDevice::Error error)

如果配对时出现异常错误,则发出信号。

(4) 主机状态模式转换信号通知


void QBluetoothLocalDevice::hostModeStateChanged(QBluetoothLocalDevice::HostMode state)

主机的状态已转换为其他主机模式。

(5) 地址配对确认通知


void QBluetoothLocalDevice::pairingDisplayConfirmation(const QBluetoothAddress &address, QString pin)

某些平台发出信号以显示地址的配对确认对话框。 要求用户确认两个设备上的密码是否相同。 必须调用pairingConfirmation()函数来指示用户是否接受或拒绝。

此信号仅通过调用requestPairing()为配对请求问题发出。 在OS X上,这种方法永远不会被调用

(6) 显示配对代码


void QBluetoothLocalDevice::pairingDisplayPinCode(const QBluetoothAddress &address, QString pin)

此信号仅通过调用requestPairing()为配对请求问题发出。

(7) 已完成配对发出信号


void QBluetoothLocalDevice::pairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing)

如果配对请求不成功,则不会发射此信号。 如果配对请求失败,则会发出error()信号。 该信号仅用于先前通过调用当前对象实例的requestPairing()请求的配对请求。

13.3 蓝牙数据收发处理(socket)

13.3.1 QBluetoothSocket类介绍


QBluetoothSocket类用于连接蓝牙设备进行数据收发服务器。

QBluetoothSocket支持两种协议类型:  L2CAP和RFCOMM。

(1) L2CAP是一种低功耗数据报导向的蓝牙套接字,Android不支持L2CAP套接字连接。

(2) RFCOMM是一个可靠的,面向流的套接字。 RFCOMM可以模拟一个RS-232串行端口。

要创建与蓝牙服务的连接,请创建适当类型的套接字并调用connectToService()传递蓝牙地址和端口号。 连接建立后QBluetoothSocket将发出connected()信号。

如果协议在平台上不受支持,调用connectToService()函数将发出UnsupportedProtocolError错误。

注意:QBluetoothSocket不支持同步读写操作。 诸如waitForReadyRead()和waitForBytesWritten()之类的函数未实现。 应该使用readyRead(),read()和write()来执行I / O操作。

13.3.2 函数介绍

(1) 构造函数


QBluetoothSocket(QBluetoothServiceInfo::ProtocosocketType, QObject *parent = Q_NULLPTR)

QBluetoothSocket(QObject *parent = Q_NULLPTR)

(2) 中止当前连接并重置套接字


void QBluetoothSocket::abort()  //关闭连接

void QBluetoothSocket::close()  //关闭连接

与disconnectFromService()不同,此函数立即关闭套接字,放弃写入缓冲区中未发出的任何数据。

注意:在Android上,中止套接字需要与Android线程进行异步交互。 因此,关联的disconnect()和stateChanged()信号将被延迟,直到线程完成关闭。

(3) 连接到蓝牙服务


void  connectToService(const QBluetoothServiceInfo &service, OpenMode openMode = ReadWrite)

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

void  connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode = ReadWrite)

该函数用于尝试连接到蓝牙服务,建立数据通信通道。

如果连接建立,QBluetoothSocket会更新连接状态,并发出connected()信号。

如果发生了错误,套接字会发出error()信号进行通知。

大多数平台在连接到远程设备之前需要配对。 否则,连接过程可能会失败。

示例:

   //开始连接蓝牙设备

    socket->connectToService(address, QBluetoothUuid(serviceUuid) ,QIODevice::ReadWrite);

在说蓝牙设备连接之前,不得不提一个非常重要的概念,就是蓝牙的Uuid。

在蓝牙中,每个服务和服务属性都由唯一地由"全球唯一标识符" (UUID)来校验。每一个这样的标识符都要在世界上保证唯一。

UUID类可表现为短整形(16或32位)和长整形(128位)UUID。

他提供了分别利用String和16位或32位数值来创建类的构造函数,提供了一个可以比较两个UUID(如果两个都是128位)的方法,还有一个可以转换一个UUID为一个字符串的方法。

  • 在Linux下用一个命令uuidgen -t可以生成一个UUID值;

在Windows下则执行命令uuidgen 。

UUID看起来就像如下的这个形式:2d266186-01fb-47c2-8d9f-10b8ec891363。

当使用生成的UUID去创建一个UUID对象,需要去掉其中的’-‘字符。

  • 常用的手机蓝牙UUID

#蓝牙串口服务

SerialPortServiceClass_UUID = '{00001101-0000-1000-8000-00805F9B34FB}'

#拨号网络服务

DialupNetworkingServiceClass_UUID = '{00001103-0000-1000-8000-00805F9B34FB}'

#信息同步服务

IrMCSyncServiceClass_UUID = '{00001104-0000-1000-8000-00805F9B34FB}'

#文件传输服务

OBEXFileTransferServiceClass_UUID = '{00001106-0000-1000-8000-00805F9B34FB}'

#蓝牙传真服务

FaxServiceClass_UUID = '{00001111-0000-1000-8000-00805F9B34FB}'

#个人局域网服务

PANUServiceClass_UUID = '{00001115-0000-1000-8000-00805F9B34FB}'

#个人局域网服务

NAPServiceClass_UUID = '{00001116-0000-1000-8000-00805F9B34FB}'

#个人局域网服务

GNServiceClass_UUID = '{00001117-0000-1000-8000-00805F9B34FB}'

#人机输入服务

HumanInterfaceDeviceServiceClass_UUID = '{00001124-0000-1000-8000-00805F9B34FB}'

#蓝牙打印服务

HCRPrintServiceClass_UUID = '{00001126-0000-1000-8000-00805F9B34FB}'

(4) 尝试断开socket连接


void QBluetoothSocket::disconnectFromService()

尝试关闭套接字。 如果有未处理的数据等待写入,QBluetoothSocket将等待所有数据写入。 最后将更新状态UnconnectedState并发出disconnect()信号。

(5) 错误信息检测函数


SocketError QBluetoothSocket::error() const   //返回错误枚举值

QString QBluetoothSocket::errorString() const  //返回可描述的字符串信息

  • 错误信息枚举值:

QBluetoothSocket::UnknownSocketError

出现未知错误。

QBluetoothSocket::NoSocketError

没有错误,用于测试。

QBluetoothSocket::HostNotFoundError

找不到远程主机。

QBluetoothSocket::ServiceNotFoundError

无法在远程主机上找到服务UUID。

QBluetoothSocket::NetworkError

尝试从套接字读取或写入返回错误

QBluetoothSocket::UnsupportedProtocolError

该平台不支持该协议。

QBluetoothSocket::OperationError

当套接字处于不允许的状态时尝试进行操作。

(6) 获取本地蓝牙设备的信息


QBluetoothAddress localAddress() const  //获取本地蓝牙地址

QString localName() const  //获取本地蓝牙名称

quint16 localPort() const   //获取本地端口号

(7) 获取对等蓝牙设备信息


QBluetoothAddress  peerAddress() const  //返回对等设备地址

QString  peerName() const  //返回对等设备名称

quint16  peerPort() const   //返回对等设备端口号

(8) 获取状态信息


SocketState QBluetoothSocket::state() const

返回套接字的当前状态。

状态枚举值:

QBluetoothSocket::UnconnectedState

套接字未连接。

QBluetoothSocket::ServiceLookupState

Socket正在查询连接参数。

QBluetoothSocket::ConnectingState

套接字尝试连接到设备。

QBluetoothSocket::ConnectedState

套接字连接到设备。

QBluetoothSocket::BoundState

套接字绑定到本地地址和端口。

QBluetoothSocket::ClosingState

套接字已连接,并且将所有待处理数据写入套接字后关闭。

QBluetoothSocket::ListeningState

套接字正在侦听传入的连接。

(9) 读写数据相关处理函数


virtuaqint64 bytesAvailable() const

返回等待读取的字节数。

virtuaqint64 bytesToWrite() const

从QIODevice :: bytesToWrite()重新实现。

返回等待写入的字节数。

virtuaboocanReadLine() const

从QIODevice :: canReadLine()重新实现。

如果可以从设备读取至少一行,则返回true

qint64 read(char *data, qint64 maxSize)

QByteArray read(qint64 maxSize)

QByteArray readAll()

qint64 readLine(char *data, qint64 maxSize)

QByteArray readLine(qint64 maxSize = 0)

从设备读取数据

qint64 write(const char *data, qint64 maxSize)

qint64 write(const char *data)

qint64 write(const QByteArray &byteArray)

virtuaqint64 readData(char *data, qint64 maxSize)

virtuaqint64 writeData(const char *data, qint64 maxSize)

向设备写数据

13.3.3 信号介绍

(1) 连接断开与连接信号通知


void connected()  //设备建立连接发出信号

void disconnected()//设备断开连接发出信号

(2) 错误信号


void error(QBluetoothLocalDevice::Error error)

错误枚举值: 上面已经介绍过了。

(3) 状态发生改变发出此信号


void QBluetoothSocket::stateChanged(QBluetoothSocket::SocketState state)

状态枚举值: 上面已经介绍过了。

13.3.4 蓝牙程序案例: 蓝牙串口调试助手


本程序使用手机蓝牙与HC-05串口蓝牙模块实现通信,进行数据传输。 (配套代码CH13-01)

(1) Main.c文件代码


#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    MainWindow w;

    w.show();

    return a.exec();

}

(2) mainwindow.cpp文件代码


#include "mainwindow.h"

#include "ui_mainwindow.h"

/*

 * 设置QT界面的样式

*/

void MainWindow::SetStyle(const QString &qssFile) {

    QFile file(qssFile);

    if (file.open(QFile::ReadOnly)) {

        QString qss = QLatin1String(file.readAll());

        qApp->setStyleSheet(qss);

        QString PaletteColor = qss.mid(20,7);

        qApp->setPalette(QPalette(QColor(PaletteColor)));

        file.close();

    }

    else

    {

        qApp->setStyleSheet("");

    }

}

static const QLatin1String serviceUuid("00001101-0000-1000-8000-00805F9B34FB");

//这个字符串里面的内容就是串口模式的Uuid

MainWindow::MainWindow(QWidget *parent) :

    QMainWindow(parent),

    ui(new Ui::MainWindow)

{

    ui->setupUi(this);

    this->SetStyle(":/qss/blue.css");     //设置样式表

    this->setWindowTitle("串口调试助手"); //设置标题

    this->setWindowIcon(QIcon(":/wbyq.ico")); //设置图标

    /*1. 实例化蓝牙相关的对象*/

    discoveryAgent = new QBluetoothDeviceDiscoveryAgent();

    localDevice = new QBluetoothLocalDevice();

    socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);

    //RfcommProtocol表示该服务使用RFCOMM套接字协议。RfcommProtocol属于模拟RS232模式,就叫串口模式

    /*2. 关联蓝牙设备相关的信号*/

    /*2.1 关联发现设备的槽函数,当扫描发现周围的蓝牙设备时,会发出deviceDiscovered信号*/

    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, static_cast<void(QBluetoothSocket::*)(QBluetoothSocket::SocketError)>(&QBluetoothSocket::error),

          [=](QBluetoothSocket::SocketError error)

    {

            ui->plainTextEdit_BluetoothInfiShow->insertPlainText(socket->errorString()); //显示错误信息

            if(QBluetoothSocket::UnknownSocketError ==error)

            {

               ui->plainTextEdit_BluetoothInfiShow->insertPlainText("位置错误\n"); //显示错误信息

            }

            if(QBluetoothSocket::NoSocketError ==error)

            {

                ui->plainTextEdit_BluetoothInfiShow->insertPlainText(" 没有错误 用于测试\n"); //显示错误信息

            }

            if(QBluetoothSocket::HostNotFoundError ==error)

            {

                  ui->plainTextEdit_BluetoothInfiShow->insertPlainText("找不到远程主机\n"); //显示错误信息

            }

            if(QBluetoothSocket::ServiceNotFoundError ==error)

            {

                     ui->plainTextEdit_BluetoothInfiShow->insertPlainText(" 无法在远程主机上找到服务UUID\n"); //显示错误信息

            }

            if(QBluetoothSocket::NetworkError ==error)

            {

                 ui->plainTextEdit_BluetoothInfiShow->insertPlainText("尝试从套接字读取或写入返回错误\n"); //显示错误信息

            }

            if(QBluetoothSocket::UnsupportedProtocolError ==error)

            {

                 ui->plainTextEdit_BluetoothInfiShow->insertPlainText(" 该平台不支持该协议\n"); //显示错误信息

            }

            if(QBluetoothSocket::OperationError ==error)

            {

                 ui->plainTextEdit_BluetoothInfiShow->insertPlainText("当套接字处于不允许的状态时尝试进行操作\n"); //显示错误信息

            }

    });

    /*3. 检查蓝牙的状态,用于设置按钮的初始状态*/

    /*3.1 检查蓝牙是否开启*/

    if(localDevice->hostMode() == QBluetoothLocalDevice::HostPoweredOff)

    {

            //如果蓝牙处于关闭状态

            ui->pushButton_OpenBluetooth->setEnabled(true);   //打开按钮

            ui->pushButton_CloseBluetooth->setEnabled(false); //关闭按钮

    }

    else    //如果蓝牙处于开启状态

    {

            ui->pushButton_OpenBluetooth->setEnabled(false);//打开按钮

            ui->pushButton_CloseBluetooth->setEnabled(true);//关闭按钮

             ui->pushButton_BluetoothScan->setEnabled(true); //设置扫描按钮可用

    }

    /*3.2 设置标签显示本地蓝牙的名称*/

    QString name_info("本机蓝牙:");

    name_info+=localDevice->name();

    ui->label_BluetoothName->setText(name_info);

     ui->pushButton_StopScan->setEnabled(false);      //设置停止扫描蓝牙的按钮不可用

     ui->plainTextEdit_BluetoothInfiShow->setEnabled(false); //设置不可编辑

}

MainWindow::~MainWindow()

{

    delete ui;

    delete discoveryAgent;

    delete localDevice;

    delete socket;

}

void MainWindow::on_pushButton_OpenBluetooth_clicked()

{

    /*请求打开蓝牙设备*/

    localDevice->powerOn();

    ui->pushButton_OpenBluetooth->setEnabled(false);//打开按钮

    ui->pushButton_CloseBluetooth->setEnabled(true);//关闭按钮

    ui->pushButton_BluetoothScan->setEnabled(true); //设置扫描按钮可用

}

void MainWindow::on_pushButton_CloseBluetooth_clicked()

{

    /*关闭蓝牙设备*/

    localDevice->setHostMode(QBluetoothLocalDevice::HostPoweredOff);

    ui->pushButton_OpenBluetooth->setEnabled(true);//打开按钮

    ui->pushButton_CloseBluetooth->setEnabled(false);//关闭按钮

    ui->pushButton_BluetoothScan->setEnabled(false); //设置扫描按钮不可用

}

void MainWindow::on_pushButton_BluetoothScan_clicked()

{

     /*开始扫描周围的蓝牙设备*/

    discoveryAgent->start();

    ui->comboBox_BluetoothDevice->clear(); //清除条目

    ui->pushButton_BluetoothScan->setEnabled(false); //设置扫描按钮不可用

    ui->pushButton_StopScan->setEnabled(true);     //设置停止扫描按钮可用

}

void MainWindow::on_pushButton_DeviceVisible_clicked()

{

    /*设置蓝牙可见,可以被周围的设备搜索到,在Android上,此模式最多只能运行5分钟。*/

    localDevice->setHostMode( QBluetoothLocalDevice::HostDiscoverable);

}

void MainWindow::on_pushButton_StopScan_clicked()

{

    /*停止扫描周围的蓝牙设备*/

    discoveryAgent->stop();

    ui->pushButton_StopScan->setEnabled(false);     //设置停止扫描按钮不可用

    ui->pushButton_BluetoothScan->setEnabled(true); //设置扫描按钮可用

}

/*当扫描到周围的设备时会调用当前的槽函数*/

void MainWindow::addBlueToothDevicesToList(const QBluetoothDeviceInfo &info)

{

   // QString labe= QString("%1 %2").arg(info.name()).arg(info.address().toString());

    QString labe= QString("%1 %2").arg(info.address().toString()).arg(info.name());

    ui->comboBox_BluetoothDevice->addItem(label); //添加字符串到comboBox上

}

//有数据可读

void MainWindow::readBluetoothDataEvent()

{

    QByteArray al= socket->readAll();

   ui->plainTextEdit_BluetoothInfiShow->insertPlainText(QString::fromLocal8Bit(all));

}

//建立连接

void MainWindow::bluetoothConnectedEvent()

{

    QMessageBox::information(this,tr("连接提示"),"蓝牙连接成功!");

    /*停止扫描周围的蓝牙设备*/

    discoveryAgent->stop();

    ui->pushButton_StopScan->setEnabled(false);     //设置停止扫描按钮不可用

    ui->pushButton_BluetoothScan->setEnabled(false); //设置扫描按钮不可用

}

//断开连接

void MainWindow::bluetoothDisconnectedEvent()

{

    QMessageBox::information(this,tr("连接提示"),"蓝牙断开连接!");

    ui->pushButton_BluetoothScan->setEnabled(true); //设置扫描按钮可用

}

//发送数据

void MainWindow::on_pushButton_SendData_clicked()

{

    QString text=ui->lineEdit_SendData->text();

    QByteArray send_data=text.toLocal8Bit();

    socket->write(send_data); //发送数据

}

//清空收到的数据

void MainWindow::on_pushButton_Clear_clicked()

{

    ui->plainTextEdit_BluetoothInfiShow->setPlainText("");

}

//连接蓝牙

void MainWindow::on_pushButton_ConnectDev_clicked()

{

    QString text = ui->comboBox_BluetoothDevice->currentText();

    int index = text.indexOf(' ');

    if(index == -1) return;

    QBluetoothAddress address(text.left(index));

    QString connect_device="开始连接蓝牙设备:\n";

    connect_device+=ui->comboBox_BluetoothDevice->currentText();

    QMessageBox::information(this,tr("连接提示"),connect_device);

    //开始连接蓝牙设备

    socket->connectToService(address, QBluetoothUuid(serviceUuid) ,QIODevice::ReadWrite);

}

//帮助提示

void MainWindow::on_pushButton_help_clicked()

{

    QMessageBox::information(this,tr("帮助提示"),"本软件用于HC-05/06系列串口蓝牙调试!\n"

                                             "暂时不支持BLE4.0版本蓝牙调试!\n"

                                             "软件作者:DS小龙哥\n"

                                             "BUG反馈:1126626497@qq.com");

}

(3) mainwindow.h文件代码


#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

#include <QBluetoothDeviceDiscoveryAgent>

#include <QBluetoothLocalDevice>

#include <QBluetoothSocket>

#include "QListWidgetItem"

#include <QMessageBox>

namespace Ui {

class MainWindow;

}

class MainWindow : public QMainWindow

{

    Q_OBJECT

public:

    explicit MainWindow(QWidget *parent = 0);

    ~MainWindow();

    QBluetoothDeviceDiscoveryAgent *discoveryAgent;  //这个是指扫描周围蓝牙设备!

    QBluetoothLocalDevice *localDevice;//是指配置获取设备的蓝牙状态信息等!

    QBluetoothSocket *socket; //指进行链接蓝牙设备,读写信息!

private slots:

    void on_pushButton_OpenBluetooth_clicked();

    void on_pushButton_CloseBluetooth_clicked();

    void on_pushButton_BluetoothScan_clicked();

    void addBlueToothDevicesToList(const QBluetoothDeviceInfo&);  //发现蓝牙设备的槽函数

    void on_pushButton_DeviceVisible_clicked();

    void on_pushButton_StopScan_clicked();

    void readBluetoothDataEvent();

    void bluetoothConnectedEvent();

    void bluetoothDisconnectedEvent();

    void on_pushButton_SendData_clicked();

    void on_pushButton_Clear_clicked();

    void SetStyle(const QString &qssFile); //样式表设置函数

    void on_pushButton_ConnectDev_clicked();

    void on_pushButton_help_clicked();

private:

    Ui::MainWindow *ui;

};

#endif // MAINWINDOW_H

(4) 程序效果截图




 13-3-1图

13.4 获取蓝牙设备信息


QBluetoothDeviceInfo类存储有关蓝牙设备的信息。

QBluetoothDeviceInfo提供有关蓝牙设备的名称,地址和设备类别的信息。

13.4.1 函数介绍

13.4.1 获取设备地址


QBluetoothAddress QBluetoothDeviceInfo::address() const

13.4.2 获取设备UUID


QList<QBluetoothUuid>

QBluetoothDeviceInfo::serviceUuids(DataCompleteness *completeness = Q_NULLPTR) const  //获取设备支持的UUID列表

void QBluetoothDeviceInfo::setServiceUuids(const QList<QBluetoothUuid> &uuids, DataCompleteness completeness)

13.4.3 检测对象是否有效


booQBluetoothDeviceInfo::isValid() const

13.4.4 返回分配给设备的名称


href="../qtcore/qstring.html" QString QBluetoothDeviceInfo::name() const



技术合作与咨询

QQ:1126626497
关注我长按二维码可识别微信号:xl1126626497



----------------------------------------------------------------------------------------------------------------------
我们尊重原创,也注重分享,文章来源于微信公众号:DS小龙哥 嵌入式技术资讯,建议关注公众号查看原文。如若侵权请联系qter@qter.org。
----------------------------------------------------------------------------------------------------------------------

鲜花

握手

雷人

路过

鸡蛋

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了