diff options
Diffstat (limited to 'src/OpcUaMonitoredNode.cpp')
| -rw-r--r-- | src/OpcUaMonitoredNode.cpp | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/OpcUaMonitoredNode.cpp b/src/OpcUaMonitoredNode.cpp new file mode 100644 index 0000000..0ffe300 --- /dev/null +++ b/src/OpcUaMonitoredNode.cpp @@ -0,0 +1,205 @@ +/** + * @file OpcUaMonitoredNode.cpp + * @brief OpcUaMonitoredNode implementation. + */ +#include "OpcUaMonitoredNode.h" +#include "OpcUaClient.h" + +#include <QMetaEnum> +#include <QOpcUaLocalizedText> + +OpcUaMonitoredNode::OpcUaMonitoredNode (QObject *parent) : QObject (parent) {} + +/* ====================================== + * Properties + * ====================================== */ + +QString +OpcUaMonitoredNode::nodeId () const +{ + return m_nodeId; +} + +void +OpcUaMonitoredNode::setNodeId (const QString &id) +{ + if (m_nodeId == id) + return; + m_nodeId = id; + emit nodeIdChanged (); + + if (!m_componentComplete) + return; + + teardownNode (); + if (OpcUaClient::instance () && OpcUaClient::instance ()->connected ()) + setupNode (); +} + +bool +OpcUaMonitoredNode::monitored () const +{ + return m_monitored; +} + +void +OpcUaMonitoredNode::setMonitored (bool monitored) +{ + if (m_monitored == monitored) + return; + m_monitored = monitored; + emit monitoredChanged (); +} + +QVariant +OpcUaMonitoredNode::value () const +{ + return m_value; +} + +OpcUaNodeInfo +OpcUaMonitoredNode::info () const +{ + return m_info; +} + +/* ====================================== + * QQmlParserStatus + * ====================================== */ + +void +OpcUaMonitoredNode::classBegin () +{ +} + +void +OpcUaMonitoredNode::componentComplete () +{ + m_componentComplete = true; + + auto *client = OpcUaClient::instance (); + if (!client) + return; + + connect (client, &OpcUaClient::connectedChanged, this, + &OpcUaMonitoredNode::handleClientConnectedChanged); + + if (client->connected () && !m_nodeId.isEmpty ()) + setupNode (); +} + +/* ====================================== + * Node lifecycle + * ====================================== */ + +void +OpcUaMonitoredNode::setupNode () +{ + if (m_node || m_nodeId.isEmpty ()) + return; + + auto *client = OpcUaClient::instance (); + if (!client || !client->connected ()) + return; + + m_node = client->opcuaClient ()->node (m_nodeId); + if (!m_node) + return; + + m_node->setParent (this); + + connect (m_node, &QOpcUaNode::attributeUpdated, this, + &OpcUaMonitoredNode::handleAttributeUpdated); + connect (m_node, &QOpcUaNode::valueAttributeUpdated, this, + &OpcUaMonitoredNode::handleValueUpdated); + + m_node->readAttributes ( + QOpcUa::NodeAttribute::Value | QOpcUa::NodeAttribute::DisplayName + | QOpcUa::NodeAttribute::Description | QOpcUa::NodeAttribute::NodeClass + | QOpcUa::NodeAttribute::DataType | QOpcUa::NodeAttribute::AccessLevel); +} + +void +OpcUaMonitoredNode::teardownNode () +{ + if (!m_node) + return; + + delete m_node; + m_node = nullptr; + + m_value.clear (); + emit valueChanged (); + + m_info = OpcUaNodeInfo{}; + emit infoChanged (); +} + +/* ====================================== + * Signal handlers + * ====================================== */ + +void +OpcUaMonitoredNode::handleAttributeUpdated (QOpcUa::NodeAttribute attr, + const QVariant &value) +{ + switch (attr) + { + case QOpcUa::NodeAttribute::DisplayName: + m_info.displayName = value.value<QOpcUaLocalizedText> ().text (); + break; + case QOpcUa::NodeAttribute::Description: + m_info.description = value.value<QOpcUaLocalizedText> ().text (); + break; + case QOpcUa::NodeAttribute::NodeClass: + { + auto me = QMetaEnum::fromType<QOpcUa::NodeClass> (); + auto nc = static_cast<QOpcUa::NodeClass> (value.toInt ()); + const char *key = me.valueToKey (static_cast<int> (nc)); + m_info.nodeClass + = key ? QLatin1StringView (key) : QStringLiteral ("Unknown"); + } + break; + case QOpcUa::NodeAttribute::DataType: + m_info.dataType = value.toString (); + break; + case QOpcUa::NodeAttribute::AccessLevel: + m_info.accessLevel = value.toUInt (); + break; + default: + return; + } + emit infoChanged (); +} + +void +OpcUaMonitoredNode::handleValueUpdated (const QVariant &value) +{ + m_value = value; + emit valueChanged (); + + m_info.status = QOpcUa::statusToString (m_node->valueAttributeError ()); + m_info.sourceTimestamp + = m_node->sourceTimestamp (QOpcUa::NodeAttribute::Value); + m_info.serverTimestamp + = m_node->serverTimestamp (QOpcUa::NodeAttribute::Value); + emit infoChanged (); +} + +void +OpcUaMonitoredNode::handleClientConnectedChanged () +{ + auto *client = OpcUaClient::instance (); + if (!client) + return; + + if (client->connected ()) + { + if (!m_nodeId.isEmpty ()) + setupNode (); + } + else + { + teardownNode (); + } +} |
