win10+Qt5.15.2实现低功耗蓝牙控制

1、前述

Qt支持低功耗蓝牙仅限于Qt5.14以上版本,不支持win7;

需要在工程项目.pro文件中添加:

QT       += bluetooth

详细介绍:https://doc.qt.io/qt-5/qtbluetooth-index.html

参考资料:https://doc.qt.io/qt-5/qtbluetooth-le-overview.html

本文源码:Qt5.15.2实现低功耗蓝牙调试助手源码-QT文档类资源-CSDN下载

低功耗蓝牙控制主要有三部分:

1、代理部分,涉及类:QBluetoothDeviceDiscoveryAgent,用于扫描设备;

2、控制器部分:涉及类:QLowEnergyController,用于连接设备、发现服务;

3、服务部分:涉及类:QLowEnergyService,用于连接服务、特征读写、Notify功能打开/关闭等;

2、代理-agent

agent.h头文件:

#ifndef AGENT_H
#define AGENT_H

#include <QObject>
#include <QBluetoothDeviceDiscoveryAgent>

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

    void startScanDevice(uint32_t timeOut);

private:
    void SendMessage(QString);
private slots:
    void onDeviceDiscovered(const QBluetoothDeviceInfo &info);
    void onError(QBluetoothDeviceDiscoveryAgent::Error err);
    void onFinished(void);
    void onCanceled(void);

signals:
    void deviceDiscovered(const QBluetoothDeviceInfo &info);
    void message(QString msg);

private:
    QBluetoothDeviceDiscoveryAgent *m_agent;
};

#endif // AGENT_H

agent.cpp源码文件:

#include "agent.h"

Agent::Agent(QObject *parent) : QObject(parent)
{
    m_agent = new QBluetoothDeviceDiscoveryAgent(this);

    if(m_agent)
    {
        connect(m_agent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(onDeviceDiscovered(QBluetoothDeviceInfo)));
        connect(m_agent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), this, SLOT(onError(QBluetoothDeviceDiscoveryAgent::Error)));
        connect(m_agent, SIGNAL(finished()), this, SLOT(onFinished()));
        connect(m_agent, SIGNAL(canceled()), this, SLOT(onCanceled()));
    }
}

void Agent::startScanDevice(uint32_t timeOut)
{
    if(m_agent)
    {
        m_agent->setLowEnergyDiscoveryTimeout(timeOut);

        m_agent->start();

        if(m_agent->isActive())
        {
            SendMessage("scanning...");
        }
    }
}

void Agent::SendMessage(QString msg)
{
    emit message(msg);
}

void Agent::onDeviceDiscovered(const QBluetoothDeviceInfo &info)
{
    emit deviceDiscovered(info);

    QString tmp = "发现设备:";
    QString str = info.address().toString() + " - " + info.name();
    SendMessage(tmp + str);
}

void Agent::onError(QBluetoothDeviceDiscoveryAgent::Error err)
{
    QString str;

    str = QString("Agent Error(%1):").arg(err);
    str += m_agent->errorString();

    SendMessage(str);
}

void Agent::onFinished()
{
    SendMessage("Agent scan finished");
}

void Agent::onCanceled()
{
    SendMessage("Agent scan canceled");
}

3、控制器-controller

controller.h头文件:

#ifndef CONTROLLER_H
#define CONTROLLER_H

#include <QObject>
#include <QLowEnergyController>
#include <QBluetoothDeviceInfo>

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

    void ConnectDevice(QBluetoothDeviceInfo info);
    void DisconnectDevice(void);

    QLowEnergyService *CreateService(QBluetoothUuid);

private:
    void SendMessage(QString);


private slots:
    void onConnected();
    void onDisconnected();
    void onStateChanged(QLowEnergyController::ControllerState state);
    void onError(QLowEnergyController::Error newError);

    void onServiceDiscovered(QBluetoothUuid);
    void onDiscoveryFinished();
    void onConnectionUpdated(const QLowEnergyConnectionParameters &parameters);

signals:
    void message(QString msg);
    void serviceDiscovered(const QBluetoothUuid &newService);

private:
    QLowEnergyController *m_controller;
};

#endif // CONTROLLER_H

controller.cpp源码文件:

#include "controller.h"

Controller::Controller(QObject *parent) : QObject(parent)
{
    m_controller = NULL;
}

void Controller::ConnectDevice(QBluetoothDeviceInfo info)
{
    if(m_controller)
    {
        m_controller->disconnectFromDevice();

        delete m_controller;

        m_controller = NULL;
    }

    m_controller = QLowEnergyController::createCentral(info);
    connect(m_controller, SIGNAL(connected()), this, SLOT(onConnected()));
    connect(m_controller, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
    connect(m_controller, SIGNAL(stateChanged(QLowEnergyController::ControllerState)), this, SLOT(onStateChanged(QLowEnergyController::ControllerState)));
    connect(m_controller, SIGNAL(error(QLowEnergyController::Error)), this, SLOT(onError(QLowEnergyController::Error)));

    connect(m_controller, SIGNAL(serviceDiscovered(QBluetoothUuid)), this, SLOT(onServiceDiscovered(QBluetoothUuid)));
    connect(m_controller, SIGNAL(discoveryFinished()), this, SLOT(onDiscoveryFinished()));
    connect(m_controller, SIGNAL(connectionUpdated(QLowEnergyConnectionParameters)), this, SLOT(onConnectionUpdated(QLowEnergyConnectionParameters)));

    m_controller->connectToDevice();
}

void Controller::DisconnectDevice()
{
    if(m_controller)
    {
        m_controller->disconnectFromDevice();
    }
}

QLowEnergyService * Controller::CreateService(QBluetoothUuid serviceUUID)
{
    if(m_controller)
    {
        return m_controller->createServiceObject(serviceUUID);
    }
    else
    {
        return NULL;
    }
}

void Controller::SendMessage(QString str)
{
    emit message(str);
}

void Controller::onConnected()
{
    if(m_controller)
    {
        m_controller->discoverServices();

        SendMessage("device connected");
    }
}

void Controller::onDisconnected()
{
    SendMessage("device disconnected");
}

void Controller::onStateChanged(QLowEnergyController::ControllerState state)
{
    const QString stateString[] = {
        "UnconnectedState",
        "ConnectingState",
        "ConnectedStatez",
        "DiscoveringState",
        "DiscoveredState",
        "ClosingState",
        "AdvertisingState",
    };

    if(state < stateString->size())
    {
        SendMessage(stateString[state]);
    }
}

void Controller::onError(QLowEnergyController::Error newError)
{
    if(m_controller)
    {
        QString str;

        str = QString("Controller Error(%1):").arg(newError);
        str += m_controller->errorString();

        SendMessage(str);
    }
}

void Controller::onServiceDiscovered(QBluetoothUuid serviceUUID)
{
    emit serviceDiscovered(serviceUUID);
}

void Controller::onDiscoveryFinished()
{
    SendMessage("service discovery finished");
}

void Controller::onConnectionUpdated(const QLowEnergyConnectionParameters &parameters)
{
    SendMessage("controller connect updated");
}


4、服务-service

service.h头文件:

#ifndef SERVICE_H
#define SERVICE_H

#include <QObject>
#include <QLowEnergyService>

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

    void ConnectService(QLowEnergyService *);
    void SendMessage(QString);
    void OpenNotify(QLowEnergyCharacteristic ch, bool flag);
    void ReadCharacteristic(QLowEnergyCharacteristic ch);
    void WriteCharacteristic(QLowEnergyCharacteristic ch, QByteArray arr);

private slots:
    void onStateChanged(QLowEnergyService::ServiceState newState);
    void onCharacteristicChanged(const QLowEnergyCharacteristic &info,
                               const QByteArray &value);
    void onCharacteristicRead(const QLowEnergyCharacteristic &info,
                            const QByteArray &value);
    void onCharacteristicWritten(const QLowEnergyCharacteristic &info,
                               const QByteArray &value);
    void onDescriptorRead(const QLowEnergyDescriptor &info,
                        const QByteArray &value);
    void onDescriptorWritten(const QLowEnergyDescriptor &info,
                           const QByteArray &value);
    void onError(QLowEnergyService::ServiceError error);

signals:
    void discoveryCharacteristic(QLowEnergyCharacteristic);
    void message(QString);

private:
    QLowEnergyService * m_service;

};

#endif // SERVICE_H

service.cpp源码文件:

#include "service.h"

Service::Service(QObject *parent) : QObject(parent)
{
    m_service = NULL;
}

void Service::ConnectService(QLowEnergyService * service)
{
    m_service = service;
    if(m_service)
    {
        if(m_service->state() == QLowEnergyService::ServiceDiscovered)
        {
            onStateChanged(QLowEnergyService::ServiceDiscovered);
        }
        else
        {
            connect(m_service, SIGNAL(stateChanged(QLowEnergyService::ServiceState)), this, SLOT(onStateChanged(QLowEnergyService::ServiceState)));
            connect(m_service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), this, SLOT(onCharacteristicChanged(QLowEnergyCharacteristic, QByteArray)));
            connect(m_service, SIGNAL(characteristicRead(QLowEnergyCharacteristic, QByteArray)), this, SLOT(onCharacteristicRead(QLowEnergyCharacteristic, QByteArray)));
            connect(m_service, SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)), this, SLOT(onCharacteristicWritten(QLowEnergyCharacteristic, QByteArray)));
            connect(m_service, SIGNAL(descriptorRead(QLowEnergyCharacteristic, QByteArray)), this, SLOT(onDescriptorRead(QLowEnergyCharacteristic, QByteArray)));
            connect(m_service, SIGNAL(descriptorWritten(QLowEnergyCharacteristic, QByteArray)), this, SLOT(onDescriptorWritten(QLowEnergyCharacteristic, QByteArray)));
            connect(m_service, SIGNAL(error(QLowEnergyService::ServiceError)), this, SLOT(onError(QLowEnergyService::ServiceError)));

            m_service->discoverDetails();
        }
    }
}

void Service::SendMessage(QString msg)
{
    emit message(msg);
}

void Service::OpenNotify(QLowEnergyCharacteristic ch, bool flag)
{
    if(m_service)
    {
        if(ch.isValid())
        {
            if(ch.properties() & QLowEnergyCharacteristic::Notify)
            {
                QLowEnergyDescriptor d = ch.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
                if(d.isValid())
                {
                    if(true == flag)
                    {
                        m_service->writeDescriptor(d, QByteArray::fromHex("0100"));
                    }
                    else
                    {
                        m_service->writeDescriptor(d, QByteArray::fromHex("0000"));
                    }
                }
            }
        }
    }
}

void Service::ReadCharacteristic(QLowEnergyCharacteristic ch)
{
    if(m_service)
    {
        if(ch.isValid())
        {
            if(ch.properties() & QLowEnergyCharacteristic::Read)
            {
                m_service->readCharacteristic(ch);
            }
        }
    }
}

void Service::WriteCharacteristic(QLowEnergyCharacteristic ch, QByteArray arr)
{
    if(m_service)
    {
        if(ch.isValid())
        {
            if(ch.properties() & QLowEnergyCharacteristic::Write)
            {
                m_service->writeCharacteristic(ch, arr, QLowEnergyService::WriteWithResponse);
            }
            else if(ch.properties() & QLowEnergyCharacteristic::WriteNoResponse)
            {
                m_service->writeCharacteristic(ch, arr, QLowEnergyService::WriteWithoutResponse);
            }
            else if(ch.properties() & QLowEnergyCharacteristic::WriteSigned)
            {
                m_service->writeCharacteristic(ch, arr, QLowEnergyService::WriteSigned);
            }
        }

    }
}

void Service::onStateChanged(QLowEnergyService::ServiceState newState)
{
    if(m_service)
    {
        switch(newState)
        {
            case QLowEnergyService::DiscoveringServices:
            {
                SendMessage("Discovering services...");
            }
            break;

            case QLowEnergyService::DiscoveryRequired:
            {
                SendMessage("require discover services...");
            }
            break;

            case QLowEnergyService::ServiceDiscovered:
            {
                SendMessage("Discovered services");
                QList<QLowEnergyCharacteristic> characteristics = m_service->characteristics();

                foreach(QLowEnergyCharacteristic ch, characteristics)
                {
                    emit discoveryCharacteristic(ch);
                }
            }
            break;

            default:
            break;
        }
    }
}

void Service::onCharacteristicChanged(const QLowEnergyCharacteristic &info, const QByteArray &value)
{
    QString ch = info.uuid().toString() + " - Characteristic Changed:" + QString(value);
    SendMessage(ch);
}

void Service::onCharacteristicRead(const QLowEnergyCharacteristic &info, const QByteArray &value)
{
    QString ch = info.uuid().toString() + " - Characteristic read:" + QString(value);
    SendMessage(ch);
}

void Service::onCharacteristicWritten(const QLowEnergyCharacteristic &info, const QByteArray &value)
{
    QString ch = info.uuid().toString() + " - Characteristic written:" + QString(value);
    SendMessage(ch);
}

void Service::onDescriptorRead(const QLowEnergyDescriptor &info, const QByteArray &value)
{
    QString ch = info.uuid().toString() + " - descriptor read:" + QString(value);
    SendMessage(ch);
}

void Service::onDescriptorWritten(const QLowEnergyDescriptor &info, const QByteArray &value)
{
    QString ch = info.uuid().toString() + " - descriptor written:" + QString(value);
    SendMessage(ch);
}

void Service::onError(QLowEnergyService::ServiceError error)
{

    const QString ServiceError[] {
        "NoError",
        "OperationError",
        "CharacteristicWriteError",
        "DescriptorWriteError",
        "UnknownError",
        "CharacteristicReadError",
        "DescriptorReadError"
    };

    if(error < ServiceError->size())
    {
        QString str;

        str = QString("service Error(%1):").arg(error);
        str += ServiceError[error];

        SendMessage(str);
    }
}

5、实现界面:

  • 9
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值