summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Keller <Rainer.Keller@qt.io>2018-08-02 10:32:47 +0200
committerRainer Keller <Rainer.Keller@qt.io>2018-08-14 05:44:40 +0000
commit111adffce2c1766fe245e9e4bc69e23050c9b692 (patch)
tree4b2287c50edaf625f9261c0f11d2680ea921fe29
parent7736c937ef176bcff50926fc9d6a81a0c267389e (diff)
Namespace autoupdate
The namespace array node will be watched for changes so that the namespaceArrayUpdated signal will be emitted without calling updateNamespaceArray beforehand. Change-Id: I8bd628cf6794d755065def0e4a0513dc56be6638 Reviewed-by: Jannis Völker <jannis.voelker@basyskom.com> Reviewed-by: Rainer Keller <Rainer.Keller@qt.io>
-rw-r--r--src/opcua/client/qopcuaclient.cpp53
-rw-r--r--src/opcua/client/qopcuaclient.h5
-rw-r--r--src/opcua/client/qopcuaclient_p.h4
-rw-r--r--src/opcua/client/qopcuaclientprivate.cpp47
-rw-r--r--tests/auto/qopcuaclient/tst_client.cpp10
5 files changed, 114 insertions, 5 deletions
diff --git a/src/opcua/client/qopcuaclient.cpp b/src/opcua/client/qopcuaclient.cpp
index 741d591..de4e863 100644
--- a/src/opcua/client/qopcuaclient.cpp
+++ b/src/opcua/client/qopcuaclient.cpp
@@ -569,4 +569,57 @@ QString QOpcUaClient::backend() const
return d->m_impl->backend();
}
+/*!
+ Enables automatic update of the namespace table.
+
+ A subscription will be made to the server node and \l namespaceArrayUpdated will be emitted
+ when the array changed without calling \l updateNamespaceArray first.
+
+ \a enable Determines whether to enable or disable the autoupdate functionality.
+
+ \sa namespaceArray() namespaceArrayUpdated()
+*/
+void QOpcUaClient::setEnableNamespaceAutoupdate(bool enable)
+{
+ Q_D(QOpcUaClient);
+ d->m_enableNamespaceArrayAutoupdate = enable;
+ d->setupNamespaceArrayMonitoring();
+}
+
+/*!
+ Returns whether autoupdate of the namespace array is activated.
+*/
+bool QOpcUaClient::namespaceAutoupdateEnabled() const
+{
+ Q_D(const QOpcUaClient);
+ return d->m_enableNamespaceArrayAutoupdate;
+}
+
+/*!
+ Sets the interval for the namespace table subscription.
+
+ The subscription may be revised by the server.
+
+ \a interval determines the interval to check for changes in milliseconds. The default is once per second.
+
+ \sa QOpcUaClient::setEnableNamespaceAutoupdate(bool enable)
+*/
+void QOpcUaClient::setNamespaceAutoupdateInterval(int interval)
+{
+ Q_D(QOpcUaClient);
+ d->m_namespaceArrayUpdateInterval = interval;
+ d->setupNamespaceArrayMonitoring();
+}
+
+/*!
+ Returns the current revised update inverval of the namespace array.
+
+ \sa setNamespaceAutoupdateInterval(int interval)
+*/
+int QOpcUaClient::namespaceAutoupdateInterval() const
+{
+ Q_D(const QOpcUaClient);
+ return d->m_namespaceArrayUpdateInterval;
+}
+
QT_END_NAMESPACE
diff --git a/src/opcua/client/qopcuaclient.h b/src/opcua/client/qopcuaclient.h
index 3611855..7aca93b 100644
--- a/src/opcua/client/qopcuaclient.h
+++ b/src/opcua/client/qopcuaclient.h
@@ -105,6 +105,11 @@ public:
QString backend() const;
+ void setEnableNamespaceAutoupdate(bool enable);
+ bool namespaceAutoupdateEnabled() const;
+ void setNamespaceAutoupdateInterval(int interval);
+ int namespaceAutoupdateInterval() const;
+
Q_SIGNALS:
void connected();
void disconnected();
diff --git a/src/opcua/client/qopcuaclient_p.h b/src/opcua/client/qopcuaclient_p.h
index fe2aaa2..51ce5d0 100644
--- a/src/opcua/client/qopcuaclient_p.h
+++ b/src/opcua/client/qopcuaclient_p.h
@@ -72,6 +72,7 @@ public:
QOpcUaClient::ClientState m_state;
QOpcUaClient::ClientError m_error;
QUrl m_url;
+ bool m_enableNamespaceArrayAutoupdate;
bool checkAndSetUrl(const QUrl &url);
void setStateAndError(QOpcUaClient::ClientState state,
@@ -80,11 +81,14 @@ public:
bool updateNamespaceArray();
QStringList namespaceArray() const;
void namespaceArrayUpdated(QOpcUa::NodeAttributes attr);
+ void setupNamespaceArrayMonitoring();
private:
Q_DECLARE_PUBLIC(QOpcUaClient)
QStringList m_namespaceArray;
QScopedPointer<QOpcUaNode> m_namespaceArrayNode;
+ bool m_namespaceArrayAutoupdateEnabled;
+ unsigned int m_namespaceArrayUpdateInterval;
};
QT_END_NAMESPACE
diff --git a/src/opcua/client/qopcuaclientprivate.cpp b/src/opcua/client/qopcuaclientprivate.cpp
index 18f8487..a186bf8 100644
--- a/src/opcua/client/qopcuaclientprivate.cpp
+++ b/src/opcua/client/qopcuaclientprivate.cpp
@@ -47,13 +47,18 @@ QOpcUaClientPrivate::QOpcUaClientPrivate(QOpcUaClientImpl *impl)
, m_impl(impl)
, m_state(QOpcUaClient::Disconnected)
, m_error(QOpcUaClient::NoError)
+ , m_enableNamespaceArrayAutoupdate(false)
+ , m_namespaceArrayAutoupdateEnabled(false)
+ , m_namespaceArrayUpdateInterval(1000)
{
// callback from client implementation
QObject::connect(m_impl.data(), &QOpcUaClientImpl::stateAndOrErrorChanged,
[this](QOpcUaClient::ClientState state, QOpcUaClient::ClientError error) {
setStateAndError(state, error);
- if (state == QOpcUaClient::ClientState::Connected)
+ if (state == QOpcUaClient::ClientState::Connected) {
updateNamespaceArray();
+ setupNamespaceArrayMonitoring();
+ }
});
QObject::connect(m_impl.data(), &QOpcUaClientImpl::endpointsRequestFinished, m_impl.data(),
@@ -194,4 +199,44 @@ void QOpcUaClientPrivate::namespaceArrayUpdated(QOpcUa::NodeAttributes attr)
emit q->namespaceArrayUpdated(m_namespaceArray);
}
+void QOpcUaClientPrivate::setupNamespaceArrayMonitoring()
+{
+ Q_Q(QOpcUaClient);
+
+ if (!m_namespaceArrayNode || m_state != QOpcUaClient::ClientState::Connected)
+ return;
+
+ if (!m_enableNamespaceArrayAutoupdate && m_namespaceArrayAutoupdateEnabled) {
+ m_namespaceArrayNode->disableMonitoring(QOpcUa::NodeAttribute::Value);
+ m_namespaceArrayAutoupdateEnabled = false;
+ return;
+ }
+
+ if (m_enableNamespaceArrayAutoupdate && !m_namespaceArrayAutoupdateEnabled) {
+ QOpcUaMonitoringParameters options;
+ options.setShared(QOpcUaMonitoringParameters::SubscriptionType::Exclusive);
+ options.setMaxKeepAliveCount(std::numeric_limits<quint32>::max() - 1);
+ options.setPublishingInterval(m_namespaceArrayUpdateInterval);
+ m_namespaceArrayAutoupdateEnabled = true;
+
+ QObject::connect(m_namespaceArrayNode.data(), &QOpcUaNode::enableMonitoringFinished, q,
+ [&] (QOpcUa::NodeAttribute, QOpcUa::UaStatusCode statusCode) {
+ if (statusCode == QOpcUa::Good) {
+ // Update interval member to the revised value from the server
+ m_namespaceArrayUpdateInterval = m_namespaceArrayNode->monitoringStatus(QOpcUa::NodeAttribute::Value).publishingInterval();
+ } else {
+ m_namespaceArrayAutoupdateEnabled = m_enableNamespaceArrayAutoupdate = false;
+ }
+ }
+ );
+ QObject::connect(m_namespaceArrayNode.data(), &QOpcUaNode::attributeUpdated, q,
+ [&] (QOpcUa::NodeAttribute attr, QVariant /*value*/) {
+ namespaceArrayUpdated(attr);
+ }
+ );
+
+ m_namespaceArrayNode->enableMonitoring(QOpcUa::NodeAttribute::Value, options);
+ }
+}
+
QT_END_NAMESPACE
diff --git a/tests/auto/qopcuaclient/tst_client.cpp b/tests/auto/qopcuaclient/tst_client.cpp
index 61476f4..b48eddd 100644
--- a/tests/auto/qopcuaclient/tst_client.cpp
+++ b/tests/auto/qopcuaclient/tst_client.cpp
@@ -3298,6 +3298,10 @@ void Tst_QOpcUaClient::addNamespace()
QSignalSpy methodSpy(node.data(), &QOpcUaNode::methodCallFinished);
+ opcuaClient->setEnableNamespaceAutoupdate(true);
+ namespaceUpdatedSpy.clear();
+ namespaceChangedSpy.clear();
+
bool success = node->callMethod("ns=3;s=Test.Method.AddNamespace", args);
QVERIFY(success == true);
@@ -3308,12 +3312,10 @@ void Tst_QOpcUaClient::addNamespace()
QCOMPARE(methodSpy.at(0).at(1).value<quint16>(), namespaceArray.size());
QCOMPARE(QOpcUa::isSuccessStatus(methodSpy.at(0).at(2).value<QOpcUa::UaStatusCode>()), true);
- namespaceUpdatedSpy.clear();
- namespaceChangedSpy.clear();
- opcuaClient->updateNamespaceArray();
+ // Do not call updateNamespaceArray()
namespaceChangedSpy.wait();
- QCOMPARE(namespaceUpdatedSpy.size(), 1);
+ QVERIFY(namespaceUpdatedSpy.size() > 0);
QCOMPARE(namespaceChangedSpy.size(), 1);
auto updatedNamespaceArray = opcuaClient->namespaceArray();
QVERIFY(updatedNamespaceArray.size() == namespaceArray.size() + 1);