Qt - 无法读取特征的描述符 - BLE

时间:2021-04-09 07:33:21

标签: qt bluetooth-lowenergy

我在使用低功耗蓝牙 Qt api 读取特性时遇到问题。我正在与之通信的设备是 Decawave DWM1001 模块。我正在按照文档中的教程进行操作。我设法连接到设备,成功读取并创建了它的服务。该设备具有 UUID 为 680c21d9-c946-4c1f-9c11-baa1c21329e7 的“网络节点服务”,我正在尝试从中读取特征。我调用了 QlowEnergyController::connectToDevice() 方法,它找到了服务,然后我为它创建了一个名为 nodeService 的 QlowEnergyService 对象。

void BluetoothConnector::serviceDiscovered(const QBluetoothUuid &newService)
{
    qDebug() << "Service discovered: " << newService.toString();

    if (newService == QBluetoothUuid(nodeServiceUUID)) {
        nodeService = controller->createServiceObject(QBluetoothUuid(nodeServiceUUID), this);

        if (nodeService) {
            qDebug() << "Node service created";
            connect(nodeService, &QLowEnergyService::stateChanged, this, &BluetoothConnector::serviceStateChanged);
            connect(nodeService, &QLowEnergyService::characteristicChanged, this, &BluetoothConnector::updateCharacteristic);
            //connect(nodeService, &QLowEnergyService::descriptorWritten, this, &BLTest::confirmedDescriptorWrite);
            nodeService->discoverDetails();
        } else {
            qDebug() << "Node service not found.";
        }
    }
}

nodeService 已成功创建(我得到“节点服务已创建”日志),然后我连接服务的信号和槽,然后在 nodeService 上调用 discoverDetails()。 serviceStateChanged() 槽看起来像这样:

void BluetoothConnector::serviceStateChanged(QLowEnergyService::ServiceState newState)
{
    if (newState == QLowEnergyService::DiscoveringServices) {
        qDebug() << "Discovering services";

    } else if (newState == QLowEnergyService::ServiceDiscovered) {
        qDebug() << "Service discovered";

        const QLowEnergyCharacteristic networkIdChar = nodeService->characteristic(QBluetoothUuid(networkIdUUID));
        const QLowEnergyCharacteristic dataModeChar = nodeService->characteristic(QBluetoothUuid(dataModeUUID));
        const QLowEnergyCharacteristic locationChar = nodeService->characteristic(QBluetoothUuid(locationUUID));

        if (networkIdChar.isValid() && dataModeChar.isValid() && locationChar.isValid()) {
            auto idValue = networkIdChar.value();
            auto modeValue = dataModeChar.value();
            auto locValue = locationChar.value();

            qDebug() << "Network ID: " << idValue;
            qDebug() << "Mode: " << modeValue;
            qDebug() << "Location: " << locValue;

            auto notificationDesc = locationChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
            if (notificationDesc.isValid()) {
                qDebug() << "Notification desc valid";
                nodeService->writeDescriptor(notificationDesc, QByteArray::fromHex("0100"));
            }
        } else {
            qDebug() << "Characteristic invalid";
        }
    }
}

我得到“发现服务”日志,之后应用程序挂起一段时间,然后我得到:

"Cannot read descriptor (onDescReadFinished 3):  \"{00002902-0000-1000-8000-00805f9b34fb}\" \"{3f0afd88-7770-46b0-b5e7-9fc099598964}\" \"org.freedesktop.DBus.Error.NoReply\" \"Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.\""
"LowEnergy controller disconnected"
"Aborting onCharReadFinished due to disconnect"

它无法读取 00002902-0000-1000-8000-00805f9b34fb,这是 3f0afd88-7770-46b0-b5e7-9fc099598964 特征(特定于供应商)的 CCCD 描述符。 无法弄清楚出了什么问题以及为什么它无法从设备读取特征。我是否需要做其他事情才能使其正常工作?

谢谢。

---更新---

BluetoothConnector 类:

#include "bluetoothconnector.h"

#include <QTimer>

BluetoothConnector::BluetoothConnector(QObject *parent) : QObject(parent)
{
    configureDiscoveryAgent();
}

void BluetoothConnector::scan()
{
    agent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
}

void BluetoothConnector::connectToDevice(QString &addr)
{
    auto it = std::find_if(devices.begin(), devices.end(),
                           [&] (const QBluetoothDeviceInfo& d) { return d.address().toString() == addr; });

    if (it == devices.end())
        return;

    device = *it;
    controller = QLowEnergyController::createCentral(device, this);
    connect(controller, &QLowEnergyController::serviceDiscovered, this, &BluetoothConnector::serviceDiscovered);
    connect(controller, &QLowEnergyController::discoveryFinished, this, &BluetoothConnector::serviceScanDone);
    connect(controller, static_cast<void (QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error),
            this, [this](QLowEnergyController::Error error) {
        Q_UNUSED(error);
        qDebug() << "Controller error: " << error;
        emit controllerError();
    });
    connect(controller, &QLowEnergyController::connected, this, [this]() {
        qDebug() << "Controller connected. Search services...";
        controller->discoverServices();
    });
    connect(controller, &QLowEnergyController::disconnected, this, [this]() {
        qDebug() << "LowEnergy controller disconnected";
    });
    controller->connectToDevice();
}

void BluetoothConnector::configureDiscoveryAgent()
{
    agent = new QBluetoothDeviceDiscoveryAgent(this);
    agent->setLowEnergyDiscoveryTimeout(5000);
    connect(agent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &BluetoothConnector::addDevice);
    connect(agent, static_cast<void (QBluetoothDeviceDiscoveryAgent::*)(QBluetoothDeviceDiscoveryAgent::Error)>(&QBluetoothDeviceDiscoveryAgent::error),
            this, &BluetoothConnector::scanError);

    connect(agent, &QBluetoothDeviceDiscoveryAgent::finished, this, &BluetoothConnector::scanFinished);
    connect(agent, &QBluetoothDeviceDiscoveryAgent::canceled, this, &BluetoothConnector::scanFinished);
}

void BluetoothConnector::addDevice(const QBluetoothDeviceInfo &info)
{
    if (!devices.contains(info)) {
        qDebug() << "Found device: " << info.name();
        devices.append(info);
        emit deviceFound(info);
    }
}

void BluetoothConnector::scanError(QBluetoothDeviceDiscoveryAgent::Error error)
{
    qDebug() << "Scan error: " << error;
}

void BluetoothConnector::scanFinished()
{
    emit scanFinishedSignal();
}

void BluetoothConnector::serviceDiscovered(const QBluetoothUuid &newService)
{
    qDebug() << "Service discovered: " << newService.toString();

    if (newService == QBluetoothUuid(nodeServiceUUID)) {
        nodeService = controller->createServiceObject(QBluetoothUuid(nodeServiceUUID), this);
        qDebug() << "State: " << nodeService->state();

        if (nodeService) {
            qDebug() << "Node service created";
            connect(nodeService, &QLowEnergyService::stateChanged, this, &BluetoothConnector::serviceStateChanged);
            connect(nodeService, &QLowEnergyService::characteristicChanged, this, &BluetoothConnector::updateCharacteristic);
            connect(nodeService, &QLowEnergyService::characteristicWritten, this, &BluetoothConnector::characteristicWritten);
            connect(nodeService, QOverload<QLowEnergyService::ServiceError>::of(&QLowEnergyService::error),
                    [=](QLowEnergyService::ServiceError newError){ qDebug() << newError; });

            //connect(nodeService, &QLowEnergyService::descriptorWritten, this, &BLTest::confirmedDescriptorWrite);
            nodeService->discoverDetails();
        } else {
            qDebug() << "Node service not found.";
        }
    }
}

void BluetoothConnector::serviceScanDone()
{
    qDebug() << "Services scan done";
}

void BluetoothConnector::characteristicWritten(const QLowEnergyCharacteristic &info, const QByteArray &value)
{
    qDebug() << "Characteristic written: " << info.name();
}

void BluetoothConnector::serviceStateChanged(QLowEnergyService::ServiceState newState)
{
    qDebug() << "State changed: " << newState;

    if (newState == QLowEnergyService::ServiceDiscovered) {
        qDebug() << "Service discovered";

        const QLowEnergyCharacteristic networkIdChar = nodeService->characteristic(QBluetoothUuid(networkIdUUID));
        const QLowEnergyCharacteristic dataModeChar = nodeService->characteristic(QBluetoothUuid(dataModeUUID));
        const QLowEnergyCharacteristic locationChar = nodeService->characteristic(QBluetoothUuid(locationUUID));

        if (networkIdChar.isValid() && dataModeChar.isValid() && locationChar.isValid()) {
            auto idValue = networkIdChar.value();
            auto modeValue = dataModeChar.value();
            auto locValue = locationChar.value();

            qDebug() << "Network ID: " << idValue;
            qDebug() << "Mode: " << modeValue;
            qDebug() << "Location: " << locValue;

            auto notificationDesc = locationChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
            if (notificationDesc.isValid()) {
                qDebug() << "Notification desc valid";
                nodeService->writeDescriptor(notificationDesc, QByteArray::fromHex("0100"));
            }
        } else {
            qDebug() << "Characteristic invalid";
        }
    }
}

void BluetoothConnector::updateCharacteristic(const QLowEnergyCharacteristic &info, const QByteArray &value)
{
    if (info.uuid() == QBluetoothUuid(networkIdUUID)) {
        qDebug() << "Update ID: " << value;
    } else if (info.uuid() == QBluetoothUuid(dataModeUUID)) {
        qDebug() << "Update mode: " << value;
    } else if (info.uuid() == QBluetoothUuid(locationUUID)) {
        qDebug() << "Update location: " << value;
    }
}

1 个答案:

答案 0 :(得分:0)

我认为,问题出在远程端(您的 GATT 服务器)。 检查 QLowEnergyService::error()QLowEnergyService::charcteristicWritten() 信号,看看是否有任何响应。 您在远程端使用哪种蓝牙堆栈? 可能是,由于实施失败,您无权更改 CCCD。请检查远程端的实现。

相关问题