You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QtOpcUa仅单个节点值可被监控的问题排查求助

Qt6 OPC UA客户端仅监控到单个节点的问题

环境与需求

Ubuntu 22.04下运行Qt6控制台应用,连接多个支持OPC UA的PLC,目标是监控多个variable类型节点的值。注:无法提供完整可运行示例(无实际远程设备模拟),可补充细节。

节点处理结构体与插入逻辑

typedef struct
{
    QOpcUaNode *node; // OPC UA节点实例
    QVariant value;   // 内部存储值
    bool updated;     // 更新标记(与问题无关)
    bool enableRead;  // 是否启用读取
} Node_t;

void MyOpcUa::insertNode(QString key, QString id, bool enableRead)
{
    Node_t node; // 自定义节点结构体实例
    node.node = _opcUaClient->node(id); // 获取OPC UA节点
    node.value = QVariant();
    node.updated = false;
    node.enableRead = enableRead;

    Q_ASSERT(node.node); // 校验节点有效性

    _mapOpcNodes.insert(key, node);
    connect(node.node, &QOpcUaNode::attributeRead, this, &MyOpcUa::handleAttributes);
    connect(node.node, &QOpcUaNode::attributeUpdated, this, &MyOpcUa::handleAttributes);
    // 预期读取属性时触发handleAttributes
}

OPC UA客户端连接逻辑

void MyOpcUa::createClient()
{
    if (_opcUaClient)
    {
        delete _opcUaClient;
        _opcUaClient = nullptr;
    }

    Q_ASSERT(_opcUaClient == nullptr);

    if (_opcUaClient == nullptr)
    {
        _opcUaClient = _opcUaProvider->createClient(OPC_UA_BACKEND);
        if (!_opcUaClient)
        {
            qInfo() << ID << _name << "Connection to server failed:" << _opcUaClient->error();
            return;
        }

        connect(_opcUaClient, &QOpcUaClient::connectError, this, &MyOpcUa::connectError);
        _opcUaClient->setApplicationIdentity(_identity);
        _opcUaClient->setPkiConfiguration(*_pkiConfig);

        if (_opcUaClient->supportedUserTokenTypes().contains(QOpcUaUserTokenPolicy::TokenType::Certificate))
        {
            QOpcUaAuthenticationInformation authInfo;
            authInfo.setCertificateAuthentication();
            _opcUaClient->setAuthenticationInformation(authInfo);
        }

        connect(_opcUaClient, &QOpcUaClient::connected, this, &MyOpcUa::clientConnected);
        connect(_opcUaClient, &QOpcUaClient::disconnected, this, &MyOpcUa::clientDisconnected);
        connect(_opcUaClient, &QOpcUaClient::errorChanged, this, &MyOpcUa::clientError);
        connect(_opcUaClient, &QOpcUaClient::stateChanged, this, &MyOpcUa::clientState);
        connect(_opcUaClient, &QOpcUaClient::endpointsRequestFinished, this, &MyOpcUa::getEndpointsComplete);
        connect(_opcUaClient, &QOpcUaClient::findServersFinished, this, &MyOpcUa::findServersComplete);
    }
}

节点监控启用逻辑

void MyOpcUa::enableMonitoring()
{
   QMapIterator<QString, Node_t> i(_mapOpcNodes);
    while (i.hasNext())
    {
        i.next();
        Node_t node = i.value();
        if (node.enableRead)
        {
            qDebug() << node.node->enableMonitoring(QOpcUa::NodeAttribute::Value, QOpcUaMonitoringParameters(1000));
        }
    }
}

问题现象

  • enableMonitoring返回值全为true,但仅单个节点能被周期性读取。
  • 处理函数日志仅打印一个节点的key,手动触发读取时所有节点均正常响应。
  • 用OPC UA查看器检查目标节点,未发现节点间属性差异,目前仅udiActualOrderLengthRT节点监控正常。

属性处理函数代码

void MyOpcUa::handleAttributes()
{
    QOpcUaNode *node = qobject_cast<QOpcUaNode*>(sender());
    QString key = retrieveNode(node->nodeId());
    if (key.isEmpty())
    {
        qWarning() << ID << "Key not found" << key;
    }

    QVariant value = node->attribute(QOpcUa::NodeAttribute::Value);    
    qDebug() << key; // 打印被读取的节点key

    if (_mapOpcNodes.contains(key))
    {
        _mapOpcNodes[key].updated = true;
        _mapOpcNodes[key].value = value;
        emit valueChanged(key, value);
    }
}

更新:监控启用结果校验

新增enableMonitoringFinished信号处理函数:

void MyOpcUa::enableMonitoringFinished(QOpcUa::NodeAttribute attr, QOpcUa::UaStatusCode statusCode)
{
    qDebug() << attr << statusCode;
}

日志输出显示所有节点的监控启用均成功:

QOpcUa::NodeAttribute::Value QOpcUa::Good

疑问

代码或实现方法是否存在错误?导致仅单个节点被周期性监控的可能原因是什么?

内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 23:48:18