summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-02-20 10:41:09 +0100
committerThomas Vanbesien <tvanbesi@proton.me>2026-02-20 10:41:09 +0100
commit0012cb312e92c33f5263478d318eb82da22ee879 (patch)
treecaac374dd3716b42d13cb85b85a7f90c7d5aac45
parent11b99fda8727f2225961c0b83ecdb18674a9670a (diff)
downloadBobinkQtOpcUa-0012cb312e92c33f5263478d318eb82da22ee879.tar.gz
BobinkQtOpcUa-0012cb312e92c33f5263478d318eb82da22ee879.zip
Rename classes to OpcUa* prefix, replace BobinkNode with OpcUaMonitoredNode boilerplate
Rename BobinkAuth → OpcUaAuth, BobinkClient → OpcUaClient (C++ class names only; QML module URI and singleton name stay as Bobink). Remove BobinkNode (QQuickItem-based) and add OpcUaMonitoredNode skeleton using QObject + QQmlParserStatus, following Qt convention for non-visual QML types.
-rw-r--r--demo/Main.qml10
-rw-r--r--demo/NodePage.qml112
-rw-r--r--src/BobinkNode.cpp410
-rw-r--r--src/BobinkNode.h111
-rw-r--r--src/CMakeLists.txt12
-rw-r--r--src/OpcUaAuth.cpp (renamed from src/BobinkAuth.cpp)32
-rw-r--r--src/OpcUaAuth.h (renamed from src/BobinkAuth.h)12
-rw-r--r--src/OpcUaClient.cpp (renamed from src/BobinkClient.cpp)110
-rw-r--r--src/OpcUaClient.h (renamed from src/BobinkClient.h)26
-rw-r--r--src/OpcUaMonitoredNode.cpp18
-rw-r--r--src/OpcUaMonitoredNode.h31
11 files changed, 152 insertions, 732 deletions
diff --git a/demo/Main.qml b/demo/Main.qml
index 9d3e168..ca0a419 100644
--- a/demo/Main.qml
+++ b/demo/Main.qml
@@ -82,7 +82,7 @@ ApplicationWindow {
Bobink.startDiscovery();
}
- BobinkAuth {
+ OpcUaAuth {
id: auth
mode: authModeCombo.currentValue
username: usernameField.text
@@ -267,22 +267,22 @@ ApplicationWindow {
model: [
{
text: "Anonymous",
- mode: BobinkAuth.Anonymous
+ mode: OpcUaAuth.Anonymous
},
{
text: "Username / Password",
- mode: BobinkAuth.UserPass
+ mode: OpcUaAuth.UserPass
},
{
text: "Certificate",
- mode: BobinkAuth.Certificate
+ mode: OpcUaAuth.Certificate
}
]
}
GridLayout {
columns: 2
- visible: authModeCombo.currentValue === BobinkAuth.UserPass
+ visible: authModeCombo.currentValue === OpcUaAuth.UserPass
Layout.fillWidth: true
Label {
diff --git a/demo/NodePage.qml b/demo/NodePage.qml
index fd81db5..bd57583 100644
--- a/demo/NodePage.qml
+++ b/demo/NodePage.qml
@@ -1,6 +1,4 @@
-// NodePage.qml — Monitors a single OPC UA node.
-// Two instances demonstrate visibility lifecycle: switching pages
-// stops monitoring on the hidden page automatically.
+// NodePage.qml — Placeholder while OpcUaMonitoredNode is implemented.
import QtQuick
import QtQuick.Controls
@@ -14,24 +12,6 @@ Page {
required property int pageNumber
required property var logFunction
- property string monitoredNodeId: ""
- property string nodeDescription: ""
- property bool nodeWritable: true
- property bool metadataLoaded: false
-
- BobinkNode {
- id: node
- nodeId: nodePage.monitoredNodeId
- onAttributeRead: (name, val) => {
- if (name === "DisplayName")
- nodePage.nodeDescription = val.toString();
- else if (name === "AccessLevel")
- nodePage.nodeWritable = (val & 0x02) !== 0;
- nodePage.metadataLoaded = true;
- }
- onWriteError: (message) => nodePage.logFunction("WRITE: " + message)
- }
-
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
@@ -50,96 +30,8 @@ Page {
}
}
- RowLayout {
- TextField {
- id: nodeIdField
- Layout.fillWidth: true
- placeholderText: "ns=2;s=Temperature"
- enabled: !nodePage.monitoredNodeId
- }
- Button {
- text: nodePage.monitoredNodeId ? "Stop" : "Monitor"
- onClicked: {
- if (nodePage.monitoredNodeId) {
- nodePage.monitoredNodeId = "";
- nodePage.nodeDescription = "";
- nodePage.nodeWritable = true;
- nodePage.metadataLoaded = false;
- } else {
- nodePage.monitoredNodeId = nodeIdField.text;
- node.readAttribute("DisplayName");
- node.readAttribute("AccessLevel");
- }
- }
- }
- }
-
- GroupBox {
- Layout.fillWidth: true
- visible: nodePage.monitoredNodeId.length > 0
- title: nodePage.nodeDescription || nodePage.monitoredNodeId
-
- GridLayout {
- columns: 2
- width: parent.width
-
- Label { text: "Value:" }
- Label {
- text: node.value !== undefined ? node.value.toString() : "—"
- font.family: "monospace"
- font.bold: true
- }
-
- Label { text: "Status:" }
- Label {
- text: node.status === BobinkNode.Good ? "Good"
- : node.status === BobinkNode.Uncertain ? "Uncertain"
- : "Bad"
- color: node.status === BobinkNode.Good ? "green"
- : node.status === BobinkNode.Uncertain ? "orange"
- : "red"
- }
-
- Label { text: "Source TS:" }
- Label {
- text: node.sourceTimestamp.toLocaleString(
- Qt.locale(), "HH:mm:ss.zzz")
- font.family: "monospace"
- }
-
- Label { text: "Server TS:" }
- Label {
- text: node.serverTimestamp.toLocaleString(
- Qt.locale(), "HH:mm:ss.zzz")
- font.family: "monospace"
- }
- }
- }
-
- RowLayout {
- visible: nodePage.monitoredNodeId.length > 0
-
- TextField {
- id: writeField
- Layout.fillWidth: true
- enabled: nodePage.nodeWritable
- placeholderText: nodePage.metadataLoaded && !nodePage.nodeWritable
- ? "Read-only node" : "Value to write"
- }
- Button {
- text: "Write"
- enabled: nodePage.nodeWritable
- onClicked: {
- node.value = writeField.text;
- writeField.clear();
- }
- }
- }
-
Label {
- visible: nodePage.monitoredNodeId.length > 0
- && nodePage.metadataLoaded && !nodePage.nodeWritable
- text: "Read-only node"
+ text: "Node monitoring not yet available (OpcUaMonitoredNode in progress)"
font.italic: true
color: "gray"
}
diff --git a/src/BobinkNode.cpp b/src/BobinkNode.cpp
deleted file mode 100644
index 55e3b75..0000000
--- a/src/BobinkNode.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/**
- * @file BobinkNode.cpp
- * @brief QML component representing a single OPC UA node.
- */
-#include "BobinkNode.h"
-#include "BobinkClient.h"
-
-#include <QOpcUaClient>
-#include <QOpcUaMonitoringParameters>
-
-using namespace Qt::Literals::StringLiterals;
-
-static constexpr double DEFAULT_PUBLISHING_INTERVAL = 250.0; // ms
-
-/* ------------------------------------------------------------------ */
-/* Construction / destruction */
-/* ------------------------------------------------------------------ */
-
-BobinkNode::BobinkNode (QQuickItem *parent) : QQuickItem (parent) {}
-
-BobinkNode::~BobinkNode () { stopMonitoring (); }
-
-/* ------------------------------------------------------------------ */
-/* Properties */
-/* ------------------------------------------------------------------ */
-
-QString
-BobinkNode::nodeId () const
-{
- return m_nodeId;
-}
-
-void
-BobinkNode::setNodeId (const QString &id)
-{
- if (m_nodeId == id)
- return;
- m_nodeId = id;
- emit nodeIdChanged ();
-
- if (m_componentComplete && isVisible ())
- {
- stopMonitoring ();
- startMonitoring ();
- }
-}
-
-QVariant
-BobinkNode::value () const
-{
- return m_value;
-}
-
-void
-BobinkNode::setValue (const QVariant &value)
-{
- if (m_opcuaNode)
- m_opcuaNode->writeValueAttribute (value);
-}
-
-BobinkNode::NodeStatus
-BobinkNode::status () const
-{
- return m_status;
-}
-
-QDateTime
-BobinkNode::sourceTimestamp () const
-{
- return m_sourceTimestamp;
-}
-
-QDateTime
-BobinkNode::serverTimestamp () const
-{
- return m_serverTimestamp;
-}
-
-/* ------------------------------------------------------------------ */
-/* readAttribute */
-/* ------------------------------------------------------------------ */
-
-void
-BobinkNode::readAttribute (const QString &attributeName)
-{
- if (!m_opcuaNode)
- return;
-
- QOpcUa::NodeAttribute attr = attributeFromName (attributeName);
- if (attr == QOpcUa::NodeAttribute::None)
- return;
-
- m_pendingReads.insert (attr, attributeName);
- m_opcuaNode->readAttributes (attr);
-}
-
-/* ------------------------------------------------------------------ */
-/* QQuickItem lifecycle */
-/* ------------------------------------------------------------------ */
-
-void
-BobinkNode::componentComplete ()
-{
- QQuickItem::componentComplete ();
- m_componentComplete = true;
-
- auto *client = BobinkClient::instance ();
- if (client)
- connect (client, &BobinkClient::connectedChanged, this,
- &BobinkNode::handleClientConnectedChanged);
-
- if (isVisible ())
- startMonitoring ();
-}
-
-void
-BobinkNode::itemChange (ItemChange change, const ItemChangeData &data)
-{
- QQuickItem::itemChange (change, data);
-
- if (change == ItemVisibleHasChanged && m_componentComplete)
- {
- if (data.boolValue)
- startMonitoring ();
- else
- stopMonitoring ();
- }
-}
-
-/* ------------------------------------------------------------------ */
-/* Monitoring lifecycle */
-/* ------------------------------------------------------------------ */
-
-void
-BobinkNode::startMonitoring ()
-{
- if (m_opcuaNode || m_nodeId.isEmpty ())
- return;
-
- auto *client = BobinkClient::instance ();
- if (!client || !client->connected ())
- return;
-
- QOpcUaClient *opcua = client->opcuaClient ();
- if (!opcua)
- return;
-
- m_opcuaNode = opcua->node (m_nodeId);
- if (!m_opcuaNode)
- return;
-
- connect (m_opcuaNode, &QOpcUaNode::dataChangeOccurred, this,
- &BobinkNode::handleDataChange);
- connect (m_opcuaNode, &QOpcUaNode::attributeUpdated, this,
- &BobinkNode::handleAttributeUpdated);
- connect (m_opcuaNode, &QOpcUaNode::attributeWritten, this,
- &BobinkNode::handleAttributeWritten);
- connect (m_opcuaNode, &QOpcUaNode::attributeRead, this,
- &BobinkNode::handleAttributeReadFinished);
- connect (m_opcuaNode, &QOpcUaNode::enableMonitoringFinished, this,
- &BobinkNode::handleEnableMonitoringFinished);
- connect (m_opcuaNode, &QOpcUaNode::disableMonitoringFinished, this,
- &BobinkNode::handleDisableMonitoringFinished);
-
- QOpcUaMonitoringParameters params (DEFAULT_PUBLISHING_INTERVAL);
- m_opcuaNode->enableMonitoring (QOpcUa::NodeAttribute::Value, params);
-}
-
-void
-BobinkNode::stopMonitoring ()
-{
- if (!m_opcuaNode)
- return;
-
- m_pendingReads.clear ();
- delete m_opcuaNode;
- m_opcuaNode = nullptr;
-}
-
-/* ------------------------------------------------------------------ */
-/* Signal handlers */
-/* ------------------------------------------------------------------ */
-
-void
-BobinkNode::handleDataChange (QOpcUa::NodeAttribute attr, const QVariant &val)
-{
- if (attr != QOpcUa::NodeAttribute::Value)
- return;
-
- if (m_value != val)
- {
- m_value = val;
- emit valueChanged ();
- }
-
- NodeStatus newStatus = statusFromCode (m_opcuaNode->valueAttributeError ());
- if (m_status != newStatus)
- {
- m_status = newStatus;
- emit statusChanged ();
- }
-
- QDateTime srcTs
- = m_opcuaNode->sourceTimestamp (QOpcUa::NodeAttribute::Value);
- if (m_sourceTimestamp != srcTs)
- {
- m_sourceTimestamp = srcTs;
- emit sourceTimestampChanged ();
- }
-
- QDateTime srvTs
- = m_opcuaNode->serverTimestamp (QOpcUa::NodeAttribute::Value);
- if (m_serverTimestamp != srvTs)
- {
- m_serverTimestamp = srvTs;
- emit serverTimestampChanged ();
- }
-}
-
-void
-BobinkNode::handleAttributeUpdated (QOpcUa::NodeAttribute attr,
- const QVariant &val)
-{
- auto it = m_pendingReads.find (attr);
- if (it != m_pendingReads.end ())
- {
- emit attributeRead (it.value (), val);
- m_pendingReads.erase (it);
- }
-}
-
-void
-BobinkNode::handleAttributeWritten (QOpcUa::NodeAttribute attr,
- QOpcUa::UaStatusCode statusCode)
-{
- if (attr != QOpcUa::NodeAttribute::Value)
- return;
-
- if (statusCode != QOpcUa::UaStatusCode::Good)
- emit writeError (QStringLiteral ("Write failed: 0x%1")
- .arg (static_cast<quint32> (statusCode), 8, 16,
- QLatin1Char ('0')));
-}
-
-void
-BobinkNode::handleClientConnectedChanged ()
-{
- if (!BobinkClient::instance ())
- return;
-
- if (BobinkClient::instance ()->connected ())
- {
- if (m_componentComplete && isVisible ())
- startMonitoring ();
- }
- else
- {
- stopMonitoring ();
- }
-}
-
-void
-BobinkNode::handleAttributeReadFinished (QOpcUa::NodeAttributes attrs)
-{
- if (!BobinkClient::instance () || !m_opcuaNode)
- return;
-
- for (int bit = 0; bit < 27; ++bit)
- {
- auto attr = static_cast<QOpcUa::NodeAttribute> (1 << bit);
- if (!attrs.testFlag (attr))
- continue;
-
- auto sc = m_opcuaNode->attributeError (attr);
- QLatin1StringView name = nameFromAttribute (attr);
- if (sc == QOpcUa::UaStatusCode::Good)
- emit BobinkClient::instance () -> statusMessage (
- QStringLiteral ("Read %1.%2 = %3")
- .arg (m_nodeId, name,
- m_opcuaNode->attribute (attr).toString ()));
- else
- emit BobinkClient::instance () -> statusMessage (
- QStringLiteral ("Read %1.%2 failed: 0x%3")
- .arg (m_nodeId, name)
- .arg (static_cast<quint32> (sc), 8, 16, QLatin1Char ('0')));
- }
-}
-
-void
-BobinkNode::handleEnableMonitoringFinished (QOpcUa::NodeAttribute,
- QOpcUa::UaStatusCode statusCode)
-{
- if (!BobinkClient::instance ())
- return;
-
- if (statusCode == QOpcUa::Good)
- emit BobinkClient::instance () -> statusMessage (
- QStringLiteral ("Monitoring started: %1").arg (m_nodeId));
- else
- emit BobinkClient::instance ()
- -> statusMessage (QStringLiteral ("Monitoring failed for %1: 0x%2")
- .arg (m_nodeId)
- .arg (static_cast<quint32> (statusCode), 8, 16,
- QLatin1Char ('0')));
-}
-
-void
-BobinkNode::handleDisableMonitoringFinished (QOpcUa::NodeAttribute,
- QOpcUa::UaStatusCode statusCode)
-{
- if (!BobinkClient::instance ())
- return;
-
- if (statusCode == QOpcUa::Good)
- emit BobinkClient::instance () -> statusMessage (
- QStringLiteral ("Monitoring stopped: %1").arg (m_nodeId));
- else
- emit BobinkClient::instance () -> statusMessage (
- QStringLiteral ("Stop monitoring failed for %1: 0x%2")
- .arg (m_nodeId)
- .arg (static_cast<quint32> (statusCode), 8, 16,
- QLatin1Char ('0')));
-}
-
-/* ------------------------------------------------------------------ */
-/* Helpers */
-/* ------------------------------------------------------------------ */
-
-BobinkNode::NodeStatus
-BobinkNode::statusFromCode (QOpcUa::UaStatusCode code)
-{
- quint32 severity = static_cast<quint32> (code) >> 30;
- switch (severity)
- {
- case 0:
- return Good;
- case 1:
- return Uncertain;
- default:
- return Bad;
- }
-}
-
-QOpcUa::NodeAttribute
-BobinkNode::attributeFromName (const QString &name)
-{
- static const QHash<QString, QOpcUa::NodeAttribute> map = {
- { QStringLiteral ("NodeId"), QOpcUa::NodeAttribute::NodeId },
- { QStringLiteral ("NodeClass"), QOpcUa::NodeAttribute::NodeClass },
- { QStringLiteral ("BrowseName"), QOpcUa::NodeAttribute::BrowseName },
- { QStringLiteral ("DisplayName"), QOpcUa::NodeAttribute::DisplayName },
- { QStringLiteral ("Description"), QOpcUa::NodeAttribute::Description },
- { QStringLiteral ("Value"), QOpcUa::NodeAttribute::Value },
- { QStringLiteral ("DataType"), QOpcUa::NodeAttribute::DataType },
- { QStringLiteral ("ValueRank"), QOpcUa::NodeAttribute::ValueRank },
- { QStringLiteral ("ArrayDimensions"),
- QOpcUa::NodeAttribute::ArrayDimensions },
- { QStringLiteral ("AccessLevel"), QOpcUa::NodeAttribute::AccessLevel },
- { QStringLiteral ("UserAccessLevel"),
- QOpcUa::NodeAttribute::UserAccessLevel },
- { QStringLiteral ("MinimumSamplingInterval"),
- QOpcUa::NodeAttribute::MinimumSamplingInterval },
- { QStringLiteral ("Historizing"), QOpcUa::NodeAttribute::Historizing },
- { QStringLiteral ("Executable"), QOpcUa::NodeAttribute::Executable },
- { QStringLiteral ("UserExecutable"),
- QOpcUa::NodeAttribute::UserExecutable },
- };
-
- return map.value (name, QOpcUa::NodeAttribute::None);
-}
-
-QLatin1StringView
-BobinkNode::nameFromAttribute (QOpcUa::NodeAttribute attr)
-{
- switch (attr)
- {
- case QOpcUa::NodeAttribute::NodeId:
- return "NodeId"_L1;
- case QOpcUa::NodeAttribute::NodeClass:
- return "NodeClass"_L1;
- case QOpcUa::NodeAttribute::BrowseName:
- return "BrowseName"_L1;
- case QOpcUa::NodeAttribute::DisplayName:
- return "DisplayName"_L1;
- case QOpcUa::NodeAttribute::Description:
- return "Description"_L1;
- case QOpcUa::NodeAttribute::Value:
- return "Value"_L1;
- case QOpcUa::NodeAttribute::DataType:
- return "DataType"_L1;
- case QOpcUa::NodeAttribute::ValueRank:
- return "ValueRank"_L1;
- case QOpcUa::NodeAttribute::ArrayDimensions:
- return "ArrayDimensions"_L1;
- case QOpcUa::NodeAttribute::AccessLevel:
- return "AccessLevel"_L1;
- case QOpcUa::NodeAttribute::UserAccessLevel:
- return "UserAccessLevel"_L1;
- case QOpcUa::NodeAttribute::MinimumSamplingInterval:
- return "MinimumSamplingInterval"_L1;
- case QOpcUa::NodeAttribute::Historizing:
- return "Historizing"_L1;
- case QOpcUa::NodeAttribute::Executable:
- return "Executable"_L1;
- case QOpcUa::NodeAttribute::UserExecutable:
- return "UserExecutable"_L1;
- default:
- return "Unknown"_L1;
- }
-}
diff --git a/src/BobinkNode.h b/src/BobinkNode.h
deleted file mode 100644
index c37a883..0000000
--- a/src/BobinkNode.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * @file BobinkNode.h
- * @brief QML component representing a single OPC UA node.
- *
- * Inherits QQuickItem so that monitoring is automatically tied to
- * visibility: when the item (or any ancestor) becomes invisible
- * (e.g. StackView navigates away, Loader unloads), the monitored
- * item is removed from the subscription. When visible again,
- * monitoring resumes.
- */
-#ifndef BOBINKNODE_H
-#define BOBINKNODE_H
-
-#include <QDateTime>
-#include <QHash>
-#include <QOpcUaNode>
-#include <QQuickItem>
-
-class BobinkNode : public QQuickItem
-{
- Q_OBJECT
- QML_ELEMENT
-
- Q_PROPERTY (QString nodeId READ nodeId WRITE setNodeId NOTIFY nodeIdChanged)
- Q_PROPERTY (QVariant value READ value WRITE setValue NOTIFY valueChanged)
- Q_PROPERTY (NodeStatus status READ status NOTIFY statusChanged)
- Q_PROPERTY (QDateTime sourceTimestamp READ sourceTimestamp NOTIFY
- sourceTimestampChanged)
- Q_PROPERTY (QDateTime serverTimestamp READ serverTimestamp NOTIFY
- serverTimestampChanged)
-
-public:
- explicit BobinkNode (QQuickItem *parent = nullptr);
- ~BobinkNode () override;
-
- /// Simplified OPC UA status severity.
- enum NodeStatus
- {
- Good,
- Uncertain,
- Bad
- };
- Q_ENUM (NodeStatus)
-
- QString nodeId () const;
- void setNodeId (const QString &id);
-
- QVariant value () const;
- /** Setting value writes to the server; the property updates when
- * the server confirms via the monitored data change. */
- void setValue (const QVariant &value);
-
- NodeStatus status () const;
- QDateTime sourceTimestamp () const;
- QDateTime serverTimestamp () const;
-
- /** Read an attribute on demand (DisplayName, Description, DataType, …).
- * Result arrives asynchronously via attributeRead(). */
- Q_INVOKABLE void readAttribute (const QString &attributeName);
-
-signals:
- void nodeIdChanged ();
- void valueChanged ();
- void statusChanged ();
- void sourceTimestampChanged ();
- void serverTimestampChanged ();
-
- /** Emitted when a readAttribute() call completes. */
- void attributeRead (const QString &attributeName, const QVariant &value);
-
- /** Emitted when a write to the server fails. */
- void writeError (const QString &message);
-
-protected:
- void componentComplete () override;
- void itemChange (ItemChange change, const ItemChangeData &data) override;
-
-private:
- void startMonitoring ();
- void stopMonitoring ();
-
- void handleDataChange (QOpcUa::NodeAttribute attr, const QVariant &val);
- void handleAttributeUpdated (QOpcUa::NodeAttribute attr,
- const QVariant &val);
- void handleAttributeWritten (QOpcUa::NodeAttribute attr,
- QOpcUa::UaStatusCode statusCode);
- void handleClientConnectedChanged ();
- void handleAttributeReadFinished (QOpcUa::NodeAttributes attrs);
- void handleEnableMonitoringFinished (QOpcUa::NodeAttribute attr,
- QOpcUa::UaStatusCode statusCode);
- void handleDisableMonitoringFinished (QOpcUa::NodeAttribute attr,
- QOpcUa::UaStatusCode statusCode);
-
- static NodeStatus statusFromCode (QOpcUa::UaStatusCode code);
- static QOpcUa::NodeAttribute attributeFromName (const QString &name);
- static QLatin1StringView nameFromAttribute (QOpcUa::NodeAttribute attr);
-
- QString m_nodeId;
- QVariant m_value;
- NodeStatus m_status = Bad;
- QDateTime m_sourceTimestamp;
- QDateTime m_serverTimestamp;
-
- QOpcUaNode *m_opcuaNode = nullptr;
- bool m_componentComplete = false;
-
- /** Tracks in-flight readAttribute() requests (enum → original name). */
- QHash<QOpcUa::NodeAttribute, QString> m_pendingReads;
-};
-
-#endif // BOBINKNODE_H
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1292194..b0781cd 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -7,12 +7,12 @@ qt_add_qml_module(
VERSION
1.0
SOURCES
- BobinkAuth.h
- BobinkAuth.cpp
- BobinkClient.h
- BobinkClient.cpp
- BobinkNode.h
- BobinkNode.cpp
+ OpcUaAuth.h
+ OpcUaAuth.cpp
+ OpcUaClient.h
+ OpcUaClient.cpp
+ OpcUaMonitoredNode.h
+ OpcUaMonitoredNode.cpp
OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/qml/Bobink")
diff --git a/src/BobinkAuth.cpp b/src/OpcUaAuth.cpp
index 132e4be..258c9c7 100644
--- a/src/BobinkAuth.cpp
+++ b/src/OpcUaAuth.cpp
@@ -1,19 +1,19 @@
/**
- * @file BobinkAuth.cpp
- * @brief BobinkAuth implementation.
+ * @file OpcUaAuth.cpp
+ * @brief OpcUaAuth implementation.
*/
-#include "BobinkAuth.h"
+#include "OpcUaAuth.h"
-BobinkAuth::BobinkAuth (QObject *parent) : QObject (parent) {}
+OpcUaAuth::OpcUaAuth (QObject *parent) : QObject (parent) {}
-BobinkAuth::AuthMode
-BobinkAuth::mode () const
+OpcUaAuth::AuthMode
+OpcUaAuth::mode () const
{
return m_mode;
}
void
-BobinkAuth::setMode (AuthMode mode)
+OpcUaAuth::setMode (AuthMode mode)
{
if (m_mode == mode)
return;
@@ -22,13 +22,13 @@ BobinkAuth::setMode (AuthMode mode)
}
QString
-BobinkAuth::username () const
+OpcUaAuth::username () const
{
return m_username;
}
void
-BobinkAuth::setUsername (const QString &username)
+OpcUaAuth::setUsername (const QString &username)
{
if (m_username == username)
return;
@@ -37,13 +37,13 @@ BobinkAuth::setUsername (const QString &username)
}
QString
-BobinkAuth::password () const
+OpcUaAuth::password () const
{
return m_password;
}
void
-BobinkAuth::setPassword (const QString &password)
+OpcUaAuth::setPassword (const QString &password)
{
if (m_password == password)
return;
@@ -52,13 +52,13 @@ BobinkAuth::setPassword (const QString &password)
}
QString
-BobinkAuth::certPath () const
+OpcUaAuth::certPath () const
{
return m_certPath;
}
void
-BobinkAuth::setCertPath (const QString &path)
+OpcUaAuth::setCertPath (const QString &path)
{
if (m_certPath == path)
return;
@@ -67,13 +67,13 @@ BobinkAuth::setCertPath (const QString &path)
}
QString
-BobinkAuth::keyPath () const
+OpcUaAuth::keyPath () const
{
return m_keyPath;
}
void
-BobinkAuth::setKeyPath (const QString &path)
+OpcUaAuth::setKeyPath (const QString &path)
{
if (m_keyPath == path)
return;
@@ -82,7 +82,7 @@ BobinkAuth::setKeyPath (const QString &path)
}
QOpcUaAuthenticationInformation
-BobinkAuth::toAuthenticationInformation () const
+OpcUaAuth::toAuthenticationInformation () const
{
QOpcUaAuthenticationInformation info;
switch (m_mode)
diff --git a/src/BobinkAuth.h b/src/OpcUaAuth.h
index 2bd3c05..8d53c1d 100644
--- a/src/BobinkAuth.h
+++ b/src/OpcUaAuth.h
@@ -1,15 +1,15 @@
/**
- * @file BobinkAuth.h
+ * @file OpcUaAuth.h
* @brief QML component for OPC UA authentication configuration.
*/
-#ifndef BOBINKAUTH_H
-#define BOBINKAUTH_H
+#ifndef OPCUAAUTH_H
+#define OPCUAAUTH_H
#include <QObject>
#include <QOpcUaAuthenticationInformation>
#include <QQmlEngine>
-class BobinkAuth : public QObject
+class OpcUaAuth : public QObject
{
Q_OBJECT
QML_ELEMENT
@@ -34,7 +34,7 @@ public:
};
Q_ENUM (AuthMode)
- explicit BobinkAuth (QObject *parent = nullptr);
+ explicit OpcUaAuth (QObject *parent = nullptr);
AuthMode mode () const;
void setMode (AuthMode mode);
@@ -72,4 +72,4 @@ private:
QString m_keyPath;
};
-#endif // BOBINKAUTH_H
+#endif // OPCUAAUTH_H
diff --git a/src/BobinkClient.cpp b/src/OpcUaClient.cpp
index 41b7dbf..91ce47b 100644
--- a/src/BobinkClient.cpp
+++ b/src/OpcUaClient.cpp
@@ -1,9 +1,9 @@
/**
- * @file BobinkClient.cpp
- * @brief BobinkClient implementation.
+ * @file OpcUaClient.cpp
+ * @brief OpcUaClient implementation.
*/
-#include "BobinkClient.h"
-#include "BobinkAuth.h"
+#include "OpcUaClient.h"
+#include "OpcUaAuth.h"
#include <QDir>
#include <QMetaEnum>
@@ -35,17 +35,17 @@ ensurePkiDirs (const QString &base)
}
static QString
-securityPolicyUri (BobinkClient::SecurityPolicy policy)
+securityPolicyUri (OpcUaClient::SecurityPolicy policy)
{
switch (policy)
{
- case BobinkClient::Basic256Sha256:
+ case OpcUaClient::Basic256Sha256:
return QStringLiteral (
"http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256");
- case BobinkClient::Aes128_Sha256_RsaOaep:
+ case OpcUaClient::Aes128_Sha256_RsaOaep:
return QStringLiteral (
"http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep");
- case BobinkClient::Aes256_Sha256_RsaPss:
+ case OpcUaClient::Aes256_Sha256_RsaPss:
return QStringLiteral (
"http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss");
}
@@ -56,7 +56,7 @@ securityPolicyUri (BobinkClient::SecurityPolicy policy)
* Construction
* ====================================== */
-BobinkClient::BobinkClient (QObject *parent)
+OpcUaClient::OpcUaClient (QObject *parent)
: QObject (parent), m_provider (new QOpcUaProvider (this)),
m_pkiDir (defaultPkiDir ())
{
@@ -66,56 +66,56 @@ BobinkClient::BobinkClient (QObject *parent)
autoDetectPki ();
applyPki ();
connect (&m_discoveryTimer, &QTimer::timeout, this,
- &BobinkClient::doDiscovery);
+ &OpcUaClient::doDiscovery);
s_instance = this;
}
void
-BobinkClient::setupClient ()
+OpcUaClient::setupClient ()
{
m_client = m_provider->createClient (QStringLiteral ("open62541"));
if (!m_client)
{
- qWarning () << "BobinkClient: failed to create open62541 backend";
+ qWarning () << "OpcUaClient: failed to create open62541 backend";
return;
}
connect (m_client, &QOpcUaClient::stateChanged, this,
- &BobinkClient::handleStateChanged);
+ &OpcUaClient::handleStateChanged);
connect (m_client, &QOpcUaClient::endpointsRequestFinished, this,
- &BobinkClient::handleEndpointsReceived);
+ &OpcUaClient::handleEndpointsReceived);
connect (m_client, &QOpcUaClient::connectError, this,
- &BobinkClient::handleConnectError);
+ &OpcUaClient::handleConnectError);
connect (m_client, &QOpcUaClient::findServersFinished, this,
- &BobinkClient::handleFindServersFinished);
+ &OpcUaClient::handleFindServersFinished);
connect (m_client, &QOpcUaClient::errorChanged, this,
- &BobinkClient::handleClientError);
+ &OpcUaClient::handleClientError);
}
/* ======================================
* Connection
* ====================================== */
-BobinkClient *
-BobinkClient::instance ()
+OpcUaClient *
+OpcUaClient::instance ()
{
return s_instance;
}
bool
-BobinkClient::connected () const
+OpcUaClient::connected () const
{
return m_connected;
}
QString
-BobinkClient::serverUrl () const
+OpcUaClient::serverUrl () const
{
return m_serverUrl;
}
void
-BobinkClient::setServerUrl (const QString &url)
+OpcUaClient::setServerUrl (const QString &url)
{
if (m_serverUrl == url)
return;
@@ -123,14 +123,14 @@ BobinkClient::setServerUrl (const QString &url)
emit serverUrlChanged ();
}
-BobinkAuth *
-BobinkClient::auth () const
+OpcUaAuth *
+OpcUaClient::auth () const
{
return m_auth;
}
void
-BobinkClient::setAuth (BobinkAuth *auth)
+OpcUaClient::setAuth (OpcUaAuth *auth)
{
if (m_auth == auth)
return;
@@ -139,13 +139,13 @@ BobinkClient::setAuth (BobinkAuth *auth)
}
QOpcUaClient *
-BobinkClient::opcuaClient () const
+OpcUaClient::opcuaClient () const
{
return m_client;
}
void
-BobinkClient::connectToServer ()
+OpcUaClient::connectToServer ()
{
if (!m_client)
{
@@ -175,7 +175,7 @@ BobinkClient::connectToServer ()
}
void
-BobinkClient::connectDirect (SecurityPolicy policy, SecurityMode mode)
+OpcUaClient::connectDirect (SecurityPolicy policy, SecurityMode mode)
{
if (!m_client)
{
@@ -205,15 +205,15 @@ BobinkClient::connectDirect (SecurityPolicy policy, SecurityMode mode)
{
switch (m_auth->mode ())
{
- case BobinkAuth::Anonymous:
+ case OpcUaAuth::Anonymous:
tokenPolicy.setTokenType (
QOpcUaUserTokenPolicy::TokenType::Anonymous);
break;
- case BobinkAuth::UserPass:
+ case OpcUaAuth::UserPass:
tokenPolicy.setTokenType (
QOpcUaUserTokenPolicy::TokenType::Username);
break;
- case BobinkAuth::Certificate:
+ case OpcUaAuth::Certificate:
tokenPolicy.setTokenType (
QOpcUaUserTokenPolicy::TokenType::Certificate);
break;
@@ -231,14 +231,14 @@ BobinkClient::connectDirect (SecurityPolicy policy, SecurityMode mode)
}
void
-BobinkClient::disconnectFromServer ()
+OpcUaClient::disconnectFromServer ()
{
if (m_client)
m_client->disconnectFromEndpoint ();
}
void
-BobinkClient::acceptCertificate ()
+OpcUaClient::acceptCertificate ()
{
m_certAccepted = true;
if (m_certLoop)
@@ -246,7 +246,7 @@ BobinkClient::acceptCertificate ()
}
void
-BobinkClient::rejectCertificate ()
+OpcUaClient::rejectCertificate ()
{
m_certAccepted = false;
if (m_certLoop)
@@ -254,7 +254,7 @@ BobinkClient::rejectCertificate ()
}
void
-BobinkClient::handleStateChanged (QOpcUaClient::ClientState state)
+OpcUaClient::handleStateChanged (QOpcUaClient::ClientState state)
{
bool nowConnected = (state == QOpcUaClient::Connected);
if (m_connected != nowConnected)
@@ -265,7 +265,7 @@ BobinkClient::handleStateChanged (QOpcUaClient::ClientState state)
}
void
-BobinkClient::handleEndpointsReceived (
+OpcUaClient::handleEndpointsReceived (
const QList<QOpcUaEndpointDescription> &endpoints,
QOpcUa::UaStatusCode statusCode, const QUrl &)
{
@@ -291,7 +291,7 @@ BobinkClient::handleEndpointsReceived (
}
void
-BobinkClient::handleConnectError (QOpcUaErrorState *errorState)
+OpcUaClient::handleConnectError (QOpcUaErrorState *errorState)
{
if (errorState->connectionStep ()
== QOpcUaErrorState::ConnectionStep::CertificateValidation)
@@ -324,7 +324,7 @@ BobinkClient::handleConnectError (QOpcUaErrorState *errorState)
}
void
-BobinkClient::handleClientError (QOpcUaClient::ClientError error)
+OpcUaClient::handleClientError (QOpcUaClient::ClientError error)
{
if (error == QOpcUaClient::NoError)
return;
@@ -340,13 +340,13 @@ BobinkClient::handleClientError (QOpcUaClient::ClientError error)
* ====================================== */
QString
-BobinkClient::discoveryUrl () const
+OpcUaClient::discoveryUrl () const
{
return m_discoveryUrl;
}
void
-BobinkClient::setDiscoveryUrl (const QString &url)
+OpcUaClient::setDiscoveryUrl (const QString &url)
{
if (m_discoveryUrl == url)
return;
@@ -355,25 +355,25 @@ BobinkClient::setDiscoveryUrl (const QString &url)
}
bool
-BobinkClient::discovering () const
+OpcUaClient::discovering () const
{
return m_discovering;
}
const QList<QOpcUaApplicationDescription> &
-BobinkClient::discoveredServers () const
+OpcUaClient::discoveredServers () const
{
return m_discoveredServers;
}
QVariantList
-BobinkClient::servers () const
+OpcUaClient::servers () const
{
return m_serversCache;
}
void
-BobinkClient::startDiscovery ()
+OpcUaClient::startDiscovery ()
{
if (m_discoveryUrl.isEmpty () || !m_client)
return;
@@ -389,7 +389,7 @@ BobinkClient::startDiscovery ()
}
void
-BobinkClient::stopDiscovery ()
+OpcUaClient::stopDiscovery ()
{
m_discoveryTimer.stop ();
@@ -401,7 +401,7 @@ BobinkClient::stopDiscovery ()
}
void
-BobinkClient::doDiscovery ()
+OpcUaClient::doDiscovery ()
{
if (!m_client || m_discoveryUrl.isEmpty ())
return;
@@ -412,7 +412,7 @@ BobinkClient::doDiscovery ()
}
void
-BobinkClient::handleFindServersFinished (
+OpcUaClient::handleFindServersFinished (
const QList<QOpcUaApplicationDescription> &servers,
QOpcUa::UaStatusCode statusCode, const QUrl &)
{
@@ -438,13 +438,13 @@ BobinkClient::handleFindServersFinished (
* ====================================== */
QString
-BobinkClient::pkiDir () const
+OpcUaClient::pkiDir () const
{
return m_pkiDir;
}
void
-BobinkClient::setPkiDir (const QString &path)
+OpcUaClient::setPkiDir (const QString &path)
{
if (m_pkiDir == path)
return;
@@ -454,13 +454,13 @@ BobinkClient::setPkiDir (const QString &path)
}
QString
-BobinkClient::certFile () const
+OpcUaClient::certFile () const
{
return m_certFile;
}
void
-BobinkClient::setCertFile (const QString &path)
+OpcUaClient::setCertFile (const QString &path)
{
if (m_certFile == path)
return;
@@ -469,13 +469,13 @@ BobinkClient::setCertFile (const QString &path)
}
QString
-BobinkClient::keyFile () const
+OpcUaClient::keyFile () const
{
return m_keyFile;
}
void
-BobinkClient::setKeyFile (const QString &path)
+OpcUaClient::setKeyFile (const QString &path)
{
if (m_keyFile == path)
return;
@@ -484,7 +484,7 @@ BobinkClient::setKeyFile (const QString &path)
}
void
-BobinkClient::autoDetectPki ()
+OpcUaClient::autoDetectPki ()
{
if (m_pkiDir.isEmpty ())
return;
@@ -503,7 +503,7 @@ BobinkClient::autoDetectPki ()
}
void
-BobinkClient::applyPki ()
+OpcUaClient::applyPki ()
{
if (!m_client || m_pkiDir.isEmpty ())
return;
diff --git a/src/BobinkClient.h b/src/OpcUaClient.h
index 7eb6c3c..1476911 100644
--- a/src/BobinkClient.h
+++ b/src/OpcUaClient.h
@@ -1,13 +1,13 @@
/**
- * @file BobinkClient.h
+ * @file OpcUaClient.h
* @brief QML singleton managing the OPC UA connection lifecycle.
*
* Wraps QOpcUaClient into a declarative interface: LDS discovery,
* endpoint selection, PKI, and certificate trust flow.
* Single connection at a time (app-wide singleton).
*/
-#ifndef BOBINKCLIENT_H
-#define BOBINKCLIENT_H
+#ifndef OPCUACLIENT_H
+#define OPCUACLIENT_H
#include <QEventLoop>
#include <QObject>
@@ -19,9 +19,9 @@
#include <QQmlEngine>
#include <QTimer>
-class BobinkAuth;
+class OpcUaAuth;
-class BobinkClient : public QObject
+class OpcUaClient : public QObject
{
Q_OBJECT
QML_SINGLETON
@@ -31,7 +31,7 @@ class BobinkClient : public QObject
Q_PROPERTY (bool connected READ connected NOTIFY connectedChanged)
Q_PROPERTY (QString serverUrl READ serverUrl WRITE setServerUrl NOTIFY
serverUrlChanged)
- Q_PROPERTY (BobinkAuth *auth READ auth WRITE setAuth NOTIFY authChanged)
+ Q_PROPERTY (OpcUaAuth *auth READ auth WRITE setAuth NOTIFY authChanged)
/* -- Discovery -- */
Q_PROPERTY (QString discoveryUrl READ discoveryUrl WRITE setDiscoveryUrl
@@ -65,7 +65,7 @@ public:
};
Q_ENUM (SecurityPolicy)
- BobinkClient (QObject *parent = nullptr);
+ OpcUaClient (QObject *parent = nullptr);
/* -- Connection -- */
@@ -74,8 +74,8 @@ public:
QString serverUrl () const;
void setServerUrl (const QString &url);
- BobinkAuth *auth () const;
- void setAuth (BobinkAuth *auth);
+ OpcUaAuth *auth () const;
+ void setAuth (OpcUaAuth *auth);
/** @brief Discover endpoints, pick the most secure, connect. */
Q_INVOKABLE void connectToServer ();
@@ -119,7 +119,7 @@ public:
/* -- C++ only -- */
- static BobinkClient *instance ();
+ static OpcUaClient *instance ();
QOpcUaClient *opcuaClient () const;
signals:
@@ -169,7 +169,7 @@ private:
/* -- Connection -- */
QOpcUaProvider *m_provider = nullptr;
QOpcUaClient *m_client = nullptr;
- BobinkAuth *m_auth = nullptr;
+ OpcUaAuth *m_auth = nullptr;
QString m_serverUrl;
bool m_connected = false;
QEventLoop *m_certLoop = nullptr;
@@ -187,7 +187,7 @@ private:
QString m_certFile;
QString m_keyFile;
- static inline BobinkClient *s_instance = nullptr;
+ static inline OpcUaClient *s_instance = nullptr;
};
-#endif // BOBINKCLIENT_H
+#endif // OPCUACLIENT_H
diff --git a/src/OpcUaMonitoredNode.cpp b/src/OpcUaMonitoredNode.cpp
new file mode 100644
index 0000000..da66e89
--- /dev/null
+++ b/src/OpcUaMonitoredNode.cpp
@@ -0,0 +1,18 @@
+/**
+ * @file OpcUaMonitoredNode.cpp
+ * @brief OpcUaMonitoredNode implementation.
+ */
+#include "OpcUaMonitoredNode.h"
+
+OpcUaMonitoredNode::OpcUaMonitoredNode (QObject *parent) : QObject (parent) {}
+
+void
+OpcUaMonitoredNode::classBegin ()
+{
+}
+
+void
+OpcUaMonitoredNode::componentComplete ()
+{
+ m_componentComplete = true;
+}
diff --git a/src/OpcUaMonitoredNode.h b/src/OpcUaMonitoredNode.h
new file mode 100644
index 0000000..ccf3444
--- /dev/null
+++ b/src/OpcUaMonitoredNode.h
@@ -0,0 +1,31 @@
+/**
+ * @file OpcUaMonitoredNode.h
+ * @brief QML component for monitoring a single OPC UA node.
+ *
+ * Inherits QObject + QQmlParserStatus so that initialisation is
+ * deferred until all QML bindings are applied (componentComplete).
+ */
+#ifndef OPCUAMONITOREDNODE_H
+#define OPCUAMONITOREDNODE_H
+
+#include <QObject>
+#include <QQmlEngine>
+#include <QQmlParserStatus>
+
+class OpcUaMonitoredNode : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES (QQmlParserStatus)
+ QML_ELEMENT
+
+public:
+ explicit OpcUaMonitoredNode (QObject *parent = nullptr);
+
+ void classBegin () override;
+ void componentComplete () override;
+
+private:
+ bool m_componentComplete = false;
+};
+
+#endif // OPCUAMONITOREDNODE_H