| 1 | // Copyright (C) 2016 basysKom GmbH, opensource@basyskom.com |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
| 3 | |
| 4 | #include <private/qopcuabackend_p.h> |
| 5 | #include <private/qopcuaclientimpl_p.h> |
| 6 | #include <QtOpcUa/qopcuamonitoringparameters.h> |
| 7 | #include "qopcuaclient_p.h" |
| 8 | #include "qopcuaerrorstate.h" |
| 9 | |
| 10 | QT_BEGIN_NAMESPACE |
| 11 | |
| 12 | QOpcUaClientImpl::QOpcUaClientImpl(QObject *parent) |
| 13 | : QObject(parent) |
| 14 | , m_client(nullptr) |
| 15 | , m_handleCounter(0) |
| 16 | {} |
| 17 | |
| 18 | QOpcUaClientImpl::~QOpcUaClientImpl() |
| 19 | {} |
| 20 | |
| 21 | bool QOpcUaClientImpl::registerNode(QPointer<QOpcUaNodeImpl> obj) |
| 22 | { |
| 23 | if (m_handles.size() == (std::numeric_limits<int>::max)()) |
| 24 | return false; |
| 25 | |
| 26 | while (true) { |
| 27 | ++m_handleCounter; |
| 28 | |
| 29 | if (!m_handles.contains(key: m_handleCounter)) { |
| 30 | obj->setHandle(m_handleCounter); |
| 31 | m_handles[m_handleCounter] = obj; |
| 32 | return true; |
| 33 | } |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | void QOpcUaClientImpl::unregisterNode(QPointer<QOpcUaNodeImpl> obj) |
| 38 | { |
| 39 | m_handles.remove(key: obj->handle()); |
| 40 | } |
| 41 | |
| 42 | void QOpcUaClientImpl::connectBackendWithClient(QOpcUaBackend *backend) |
| 43 | { |
| 44 | connect(sender: backend, signal: &QOpcUaBackend::attributesRead, context: this, slot: &QOpcUaClientImpl::handleAttributesRead); |
| 45 | connect(sender: backend, signal: &QOpcUaBackend::stateAndOrErrorChanged, context: this, slot: &QOpcUaClientImpl::stateAndOrErrorChanged); |
| 46 | connect(sender: backend, signal: &QOpcUaBackend::attributeWritten, context: this, slot: &QOpcUaClientImpl::handleAttributeWritten); |
| 47 | connect(sender: backend, signal: &QOpcUaBackend::dataChangeOccurred, context: this, slot: &QOpcUaClientImpl::handleDataChangeOccurred); |
| 48 | connect(sender: backend, signal: &QOpcUaBackend::monitoringEnableDisable, context: this, slot: &QOpcUaClientImpl::handleMonitoringEnableDisable); |
| 49 | connect(sender: backend, signal: &QOpcUaBackend::monitoringStatusChanged, context: this, slot: &QOpcUaClientImpl::handleMonitoringStatusChanged); |
| 50 | connect(sender: backend, signal: &QOpcUaBackend::methodCallFinished, context: this, slot: &QOpcUaClientImpl::handleMethodCallFinished); |
| 51 | connect(sender: backend, signal: &QOpcUaBackend::browseFinished, context: this, slot: &QOpcUaClientImpl::handleBrowseFinished); |
| 52 | connect(sender: backend, signal: &QOpcUaBackend::resolveBrowsePathFinished, context: this, slot: &QOpcUaClientImpl::handleResolveBrowsePathFinished); |
| 53 | connect(sender: backend, signal: &QOpcUaBackend::eventOccurred, context: this, slot: &QOpcUaClientImpl::handleNewEvent); |
| 54 | connect(sender: backend, signal: &QOpcUaBackend::endpointsRequestFinished, context: this, slot: &QOpcUaClientImpl::endpointsRequestFinished); |
| 55 | connect(sender: backend, signal: &QOpcUaBackend::findServersFinished, context: this, slot: &QOpcUaClientImpl::findServersFinished); |
| 56 | connect(sender: backend, signal: &QOpcUaBackend::readNodeAttributesFinished, context: this, slot: &QOpcUaClientImpl::readNodeAttributesFinished); |
| 57 | connect(sender: backend, signal: &QOpcUaBackend::writeNodeAttributesFinished, context: this, slot: &QOpcUaClientImpl::writeNodeAttributesFinished); |
| 58 | connect(sender: backend, signal: &QOpcUaBackend::addNodeFinished, context: this, slot: &QOpcUaClientImpl::addNodeFinished); |
| 59 | connect(sender: backend, signal: &QOpcUaBackend::deleteNodeFinished, context: this, slot: &QOpcUaClientImpl::deleteNodeFinished); |
| 60 | connect(sender: backend, signal: &QOpcUaBackend::addReferenceFinished, context: this, slot: &QOpcUaClientImpl::addReferenceFinished); |
| 61 | connect(sender: backend, signal: &QOpcUaBackend::deleteReferenceFinished, context: this, slot: &QOpcUaClientImpl::deleteReferenceFinished); |
| 62 | // This needs to be blocking queued because it is called from another thread, which needs to wait for a result. |
| 63 | connect(sender: backend, signal: &QOpcUaBackend::connectError, context: this, slot: &QOpcUaClientImpl::connectError, type: Qt::BlockingQueuedConnection); |
| 64 | connect(sender: backend, signal: &QOpcUaBackend::passwordForPrivateKeyRequired, context: this, slot: &QOpcUaClientImpl::passwordForPrivateKeyRequired, type: Qt::BlockingQueuedConnection); |
| 65 | connect(sender: backend, signal: &QOpcUaBackend::registerNodesFinished, context: this, slot: &QOpcUaClientImpl::registerNodesFinished); |
| 66 | connect(sender: backend, signal: &QOpcUaBackend::unregisterNodesFinished, context: this, slot: &QOpcUaClientImpl::unregisterNodesFinished); |
| 67 | } |
| 68 | |
| 69 | void QOpcUaClientImpl::handleAttributesRead(quint64 handle, QList<QOpcUaReadResult> attr, QOpcUa::UaStatusCode serviceResult) |
| 70 | { |
| 71 | auto it = m_handles.constFind(key: handle); |
| 72 | if (it != m_handles.constEnd() && !it->isNull()) |
| 73 | emit (*it)->attributesRead(attr, serviceResult); |
| 74 | } |
| 75 | |
| 76 | void QOpcUaClientImpl::handleAttributeWritten(quint64 handle, QOpcUa::NodeAttribute attr, const QVariant &value, QOpcUa::UaStatusCode statusCode) |
| 77 | { |
| 78 | auto it = m_handles.constFind(key: handle); |
| 79 | if (it != m_handles.constEnd() && !it->isNull()) |
| 80 | emit (*it)->attributeWritten(attr, value, statusCode); |
| 81 | } |
| 82 | |
| 83 | void QOpcUaClientImpl::handleDataChangeOccurred(quint64 handle, const QOpcUaReadResult &value) |
| 84 | { |
| 85 | auto it = m_handles.constFind(key: handle); |
| 86 | if (it != m_handles.constEnd() && !it->isNull()) |
| 87 | emit (*it)->dataChangeOccurred(attr: value.attribute(), value); |
| 88 | } |
| 89 | |
| 90 | void QOpcUaClientImpl::handleMonitoringEnableDisable(quint64 handle, QOpcUa::NodeAttribute attr, bool subscribe, QOpcUaMonitoringParameters status) |
| 91 | { |
| 92 | auto it = m_handles.constFind(key: handle); |
| 93 | if (it != m_handles.constEnd() && !it->isNull()) |
| 94 | emit (*it)->monitoringEnableDisable(attr, subscribe, status); |
| 95 | } |
| 96 | |
| 97 | void QOpcUaClientImpl::handleMonitoringStatusChanged(quint64 handle, QOpcUa::NodeAttribute attr, QOpcUaMonitoringParameters::Parameters items, QOpcUaMonitoringParameters param) |
| 98 | { |
| 99 | auto it = m_handles.constFind(key: handle); |
| 100 | if (it != m_handles.constEnd() && !it->isNull()) |
| 101 | emit (*it)->monitoringStatusChanged(attr, items, param); |
| 102 | } |
| 103 | |
| 104 | void QOpcUaClientImpl::handleMethodCallFinished(quint64 handle, QString methodNodeId, QVariant result, QOpcUa::UaStatusCode statusCode) |
| 105 | { |
| 106 | auto it = m_handles.constFind(key: handle); |
| 107 | if (it != m_handles.constEnd() && !it->isNull()) |
| 108 | emit (*it)->methodCallFinished(methodNodeId, result, statusCode); |
| 109 | } |
| 110 | |
| 111 | void QOpcUaClientImpl::handleBrowseFinished(quint64 handle, const QList<QOpcUaReferenceDescription> &children, QOpcUa::UaStatusCode statusCode) |
| 112 | { |
| 113 | auto it = m_handles.constFind(key: handle); |
| 114 | if (it != m_handles.constEnd() && !it->isNull()) |
| 115 | emit (*it)->browseFinished(children, statusCode); |
| 116 | } |
| 117 | |
| 118 | void QOpcUaClientImpl::handleResolveBrowsePathFinished(quint64 handle, QList<QOpcUaBrowsePathTarget> targets, |
| 119 | QList<QOpcUaRelativePathElement> path, QOpcUa::UaStatusCode status) |
| 120 | { |
| 121 | auto it = m_handles.constFind(key: handle); |
| 122 | if (it != m_handles.constEnd() && !it->isNull()) |
| 123 | emit (*it)->resolveBrowsePathFinished(targets, path, status); |
| 124 | } |
| 125 | |
| 126 | void QOpcUaClientImpl::handleNewEvent(quint64 handle, QVariantList eventFields) |
| 127 | { |
| 128 | auto it = m_handles.constFind(key: handle); |
| 129 | if (it != m_handles.constEnd() && !it->isNull()) |
| 130 | emit (*it)->eventOccurred(eventFields); |
| 131 | } |
| 132 | |
| 133 | QT_END_NAMESPACE |
| 134 | |