summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-02-20 14:50:39 +0100
committerThomas Vanbesien <tvanbesi@proton.me>2026-02-20 14:50:39 +0100
commit6c142a234673e442561b2c050b727aa4400177d8 (patch)
treebc44b564b67f7644dde37dd2147b63080a1611cf
parent47227acd25c59a1d4b2961c0e1b1eb879e68adec (diff)
downloadBobinkQtOpcUa-6c142a234673e442561b2c050b727aa4400177d8.tar.gz
BobinkQtOpcUa-6c142a234673e442561b2c050b727aa4400177d8.zip
Wire monitored property to OPC UA monitored items
The monitored bool now calls enableMonitoring/disableMonitoring on the Value attribute. Adds publishingInterval property (default 100ms). Value is no longer read at init — delivered by the monitored item. Empty 4th demo page to verify monitoring stops when navigating away.
-rw-r--r--demo/NodePage.qml20
-rw-r--r--src/OpcUaMonitoredNode.cpp76
-rw-r--r--src/OpcUaMonitoredNode.h13
3 files changed, 104 insertions, 5 deletions
diff --git a/demo/NodePage.qml b/demo/NodePage.qml
index 442a6fd..a8e07d5 100644
--- a/demo/NodePage.qml
+++ b/demo/NodePage.qml
@@ -57,6 +57,12 @@ Page {
"ns=1;s=double_rw_array",
"ns=1;s=string_rw_array"
]
+ },
+ {
+ title: "Empty (Monitoring Test)",
+ description: "No nodes on this page. All previous pages are inactive,"
+ + " so the server log should show zero active monitored items.",
+ nodes: []
}
]
@@ -78,7 +84,7 @@ Page {
font.pointSize: 14
}
Label {
- text: "(" + nodePage.pageNumber + "/3)"
+ text: "(" + nodePage.pageNumber + "/" + nodePage.pages.length + ")"
color: "gray"
}
Item { Layout.fillWidth: true }
@@ -88,6 +94,16 @@ Page {
}
}
+ Label {
+ id: pageDescription
+ visible: currentPage.description !== undefined
+ text: currentPage.description || ""
+ wrapMode: Text.WordWrap
+ color: "gray"
+ font.italic: true
+ Layout.fillWidth: true
+ }
+
// Column headers
RowLayout {
Layout.fillWidth: true
@@ -216,7 +232,7 @@ Page {
Item { Layout.fillWidth: true }
Button {
text: "Next →"
- visible: nodePage.pageNumber < 3
+ visible: nodePage.pageNumber < nodePage.pages.length
onClicked: nodePage.stackRef.push("NodePage.qml", {
stackRef: nodePage.stackRef,
pageNumber: nodePage.pageNumber + 1,
diff --git a/src/OpcUaMonitoredNode.cpp b/src/OpcUaMonitoredNode.cpp
index 518ddd5..1a2da86 100644
--- a/src/OpcUaMonitoredNode.cpp
+++ b/src/OpcUaMonitoredNode.cpp
@@ -7,6 +7,7 @@
#include <QMetaEnum>
#include <QOpcUaLocalizedText>
+#include <QOpcUaMonitoringParameters>
#include <QStringList>
OpcUaMonitoredNode::OpcUaMonitoredNode (QObject *parent) : QObject (parent) {}
@@ -51,6 +52,29 @@ OpcUaMonitoredNode::setMonitored (bool monitored)
return;
m_monitored = monitored;
emit monitoredChanged ();
+
+ if (!m_componentComplete || !m_node)
+ return;
+
+ if (m_monitored)
+ startMonitoring ();
+ else
+ stopMonitoring ();
+}
+
+double
+OpcUaMonitoredNode::publishingInterval () const
+{
+ return m_publishingInterval;
+}
+
+void
+OpcUaMonitoredNode::setPublishingInterval (double interval)
+{
+ if (qFuzzyCompare (m_publishingInterval, interval))
+ return;
+ m_publishingInterval = interval;
+ emit publishingIntervalChanged ();
}
QVariant
@@ -122,11 +146,18 @@ OpcUaMonitoredNode::setupNode ()
&OpcUaMonitoredNode::handleValueUpdated);
connect (m_node, &QOpcUaNode::attributeWritten, this,
&OpcUaMonitoredNode::handleAttributeWritten);
+ connect (m_node, &QOpcUaNode::enableMonitoringFinished, this,
+ &OpcUaMonitoredNode::handleEnableMonitoringFinished);
+ connect (m_node, &QOpcUaNode::disableMonitoringFinished, this,
+ &OpcUaMonitoredNode::handleDisableMonitoringFinished);
m_node->readAttributes (
- QOpcUa::NodeAttribute::Value | QOpcUa::NodeAttribute::DisplayName
- | QOpcUa::NodeAttribute::Description | QOpcUa::NodeAttribute::NodeClass
- | QOpcUa::NodeAttribute::DataType | QOpcUa::NodeAttribute::AccessLevel);
+ QOpcUa::NodeAttribute::DisplayName | QOpcUa::NodeAttribute::Description
+ | QOpcUa::NodeAttribute::NodeClass | QOpcUa::NodeAttribute::DataType
+ | QOpcUa::NodeAttribute::AccessLevel);
+
+ if (m_monitored)
+ startMonitoring ();
}
void
@@ -153,6 +184,23 @@ OpcUaMonitoredNode::teardownNode ()
}
}
+void
+OpcUaMonitoredNode::startMonitoring ()
+{
+ if (!m_node || !m_monitored)
+ return;
+ QOpcUaMonitoringParameters params (m_publishingInterval);
+ m_node->enableMonitoring (QOpcUa::NodeAttribute::Value, params);
+}
+
+void
+OpcUaMonitoredNode::stopMonitoring ()
+{
+ if (!m_node)
+ return;
+ m_node->disableMonitoring (QOpcUa::NodeAttribute::Value);
+}
+
/* ======================================
* Signal handlers
* ====================================== */
@@ -262,6 +310,28 @@ OpcUaMonitoredNode::handleAttributeWritten (QOpcUa::NodeAttribute attr,
: QOpcUa::statusToString (statusCode));
}
+void
+OpcUaMonitoredNode::handleEnableMonitoringFinished (
+ QOpcUa::NodeAttribute attr, QOpcUa::UaStatusCode statusCode)
+{
+ if (attr != QOpcUa::NodeAttribute::Value)
+ return;
+ if (statusCode != QOpcUa::Good)
+ qWarning () << "OpcUaMonitoredNode: enableMonitoring failed for"
+ << m_nodeId << ":" << QOpcUa::statusToString (statusCode);
+}
+
+void
+OpcUaMonitoredNode::handleDisableMonitoringFinished (
+ QOpcUa::NodeAttribute attr, QOpcUa::UaStatusCode statusCode)
+{
+ if (attr != QOpcUa::NodeAttribute::Value)
+ return;
+ if (statusCode != QOpcUa::Good)
+ qWarning () << "OpcUaMonitoredNode: disableMonitoring failed for"
+ << m_nodeId << ":" << QOpcUa::statusToString (statusCode);
+}
+
/* ======================================
* Write support
* ====================================== */
diff --git a/src/OpcUaMonitoredNode.h b/src/OpcUaMonitoredNode.h
index 5895bea..3e86cb4 100644
--- a/src/OpcUaMonitoredNode.h
+++ b/src/OpcUaMonitoredNode.h
@@ -56,6 +56,8 @@ class OpcUaMonitoredNode : public QObject, public QQmlParserStatus
Q_PROPERTY (QString nodeId READ nodeId WRITE setNodeId NOTIFY nodeIdChanged)
Q_PROPERTY (
bool monitored READ monitored WRITE setMonitored NOTIFY monitoredChanged)
+ Q_PROPERTY (double publishingInterval READ publishingInterval WRITE
+ setPublishingInterval NOTIFY publishingIntervalChanged)
Q_PROPERTY (QVariant value READ value NOTIFY valueChanged)
Q_PROPERTY (bool writable READ writable NOTIFY writableChanged)
Q_PROPERTY (OpcUaNodeInfo info READ info NOTIFY infoChanged)
@@ -69,6 +71,9 @@ public:
bool monitored () const;
void setMonitored (bool monitored);
+ double publishingInterval () const;
+ void setPublishingInterval (double interval);
+
QVariant value () const;
bool writable () const;
OpcUaNodeInfo info () const;
@@ -89,6 +94,7 @@ public:
signals:
void nodeIdChanged ();
void monitoredChanged ();
+ void publishingIntervalChanged ();
void valueChanged ();
void writableChanged ();
void infoChanged ();
@@ -101,14 +107,21 @@ private slots:
void handleClientConnectedChanged ();
void handleAttributeWritten (QOpcUa::NodeAttribute attr,
QOpcUa::UaStatusCode statusCode);
+ void handleEnableMonitoringFinished (QOpcUa::NodeAttribute attr,
+ QOpcUa::UaStatusCode statusCode);
+ void handleDisableMonitoringFinished (QOpcUa::NodeAttribute attr,
+ QOpcUa::UaStatusCode statusCode);
private:
void setupNode ();
void teardownNode ();
+ void startMonitoring ();
+ void stopMonitoring ();
QVariant coerceValue (const QVariant &input) const;
QString m_nodeId;
bool m_monitored = true;
+ double m_publishingInterval = 100.0;
bool m_componentComplete = false;
QOpcUaNode *m_node = nullptr;