summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJannis Voelker <jannis.voelker@basyskom.com>2018-04-19 09:27:19 +0200
committerFrank Meerkoetter <frank.meerkoetter@basyskom.com>2018-04-30 12:42:03 +0000
commit265293a48bca407131bc0825ffffa556724159fb (patch)
treead76e352438542fe2c22a5de6ee998a909ab876e
parentc503a84a60618d9d14c0d13211283f8621316c17 (diff)
Fix node creation in the freeopcua backend
The internal string to node id converter in freeopcua does not support opaque node ids and guid conversion is case sensitive. This patch bypasses the internal node id conversion and adds a custom converter adapted from the open62541 implementation. Change-Id: I634ba91c3f3de6932c85acf3adc736c10a99c07f Reviewed-by: Frank Meerkoetter <frank.meerkoetter@basyskom.com>
-rw-r--r--src/plugins/opcua/freeopcua/qfreeopcuaclient.cpp8
-rw-r--r--src/plugins/opcua/freeopcua/qfreeopcuavalueconverter.cpp97
-rw-r--r--src/plugins/opcua/freeopcua/qfreeopcuavalueconverter.h1
3 files changed, 105 insertions, 1 deletions
diff --git a/src/plugins/opcua/freeopcua/qfreeopcuaclient.cpp b/src/plugins/opcua/freeopcua/qfreeopcuaclient.cpp
index a84aceb..9afe4ff 100644
--- a/src/plugins/opcua/freeopcua/qfreeopcuaclient.cpp
+++ b/src/plugins/opcua/freeopcua/qfreeopcuaclient.cpp
@@ -36,6 +36,7 @@
#include "qfreeopcuaclient.h"
#include "qfreeopcuanode.h"
+#include "qfreeopcuavalueconverter.h"
#include "qfreeopcuaworker.h"
#include <private/qopcuaclient_p.h>
@@ -79,8 +80,13 @@ QOpcUaNode *QFreeOpcUaClientImpl::node(const QString &nodeId)
if (!m_opcuaWorker)
return nullptr;
+ OpcUa::NodeId id = QFreeOpcUaValueConverter::stringToNodeId(nodeId);
+
+ if (id.IsNull())
+ return nullptr;
+
try {
- OpcUa::Node node = m_opcuaWorker->GetNode(nodeId.toStdString());
+ OpcUa::Node node = m_opcuaWorker->GetNode(id);
QFreeOpcUaNode *n = new QFreeOpcUaNode(node, this);
return new QOpcUaNode(n, m_client);
} catch (const std::exception &ex) {
diff --git a/src/plugins/opcua/freeopcua/qfreeopcuavalueconverter.cpp b/src/plugins/opcua/freeopcua/qfreeopcuavalueconverter.cpp
index 4591c9d..d1dd6f8 100644
--- a/src/plugins/opcua/freeopcua/qfreeopcuavalueconverter.cpp
+++ b/src/plugins/opcua/freeopcua/qfreeopcuavalueconverter.cpp
@@ -418,6 +418,103 @@ QOpcUa::UaStatusCode exceptionToStatusCode(const std::exception &ex)
return statusCode;
}
+OpcUa::NodeId stringToNodeId(const QString &id)
+{
+ const int semicolonIndex = id.indexOf(';');
+
+ if (semicolonIndex <= 0) {
+ qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << "Unable to split node id string:" << qUtf8Printable(id);
+ return OpcUa::NodeId();
+ }
+
+ QStringRef namespaceString = id.leftRef(semicolonIndex);
+ if (namespaceString.length() <= 3 || !namespaceString.startsWith(QLatin1String("ns="))) {
+ qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << "Not a valid index string in node id string:" << id;
+ return OpcUa::NodeId();
+ }
+ namespaceString = namespaceString.mid(3); // Remove "ns="
+
+ QStringRef identifierString = id.midRef(semicolonIndex + 1);
+
+ if (identifierString.length() <= 2) {
+ qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << "There is no identifier in node id string:" << id;
+ return OpcUa::NodeId();
+ }
+
+ char identifierType;
+ if (identifierString.startsWith(QLatin1String("s=")))
+ identifierType = 's';
+ else if (identifierString.startsWith(QLatin1String("i=")))
+ identifierType = 'i';
+ else if (identifierString.startsWith(QLatin1String("g=")))
+ identifierType = 'g';
+ else if (identifierString.startsWith(QLatin1String("b=")))
+ identifierType = 'b';
+ else {
+ qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << "There is no valid identifier type in node id string:" << id;
+ return OpcUa::NodeId();
+ }
+ identifierString = identifierString.mid(2); // Remove identifier type
+
+ bool ok = false;
+ quint16 index = static_cast<quint16>(namespaceString.toUInt(&ok));
+
+ if (!ok) {
+ qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << "Not a valid namespace index in node id string:" << id;
+ return OpcUa::NodeId();
+ }
+
+ switch (identifierType) {
+ case 'i': {
+ bool isNumber;
+ quint32 identifier = static_cast<quint32>(identifierString.toUInt(&isNumber));
+ if (isNumber)
+ return OpcUa::NumericNodeId(identifier, index);
+ else
+ qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << id << "does not contain a valid numeric identifier";
+ break;
+ }
+ case 's': {
+ if (identifierString.length() > 0) {
+ return OpcUa::StringNodeId(identifierString.toString().toStdString(), index);
+ }
+ else
+ qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << id << "does not contain a valid string identifier";
+ break;
+ }
+ case 'g': {
+ QUuid uuid(identifierString.toString());
+
+ if (uuid.isNull()) {
+ qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << id << "does not contain a valid guid identifier";
+ }
+
+ OpcUa::Guid guid;
+ guid.Data1 = uuid.data1;
+ guid.Data2 = uuid.data2;
+ guid.Data3 = uuid.data3;
+ std::memcpy(guid.Data4, uuid.data4, sizeof(uuid.data4));
+ return OpcUa::GuidNodeId(guid, index);
+ }
+ case 'b': {
+ const QByteArray temp = QByteArray::fromBase64(identifierString.toLocal8Bit());
+ if (temp.size() > 0) {
+ OpcUa::NodeId result;
+ result.Encoding = OpcUa::NodeIdEncoding::EV_BYTE_STRING;
+ result.BinaryData.NamespaceIndex = index;
+ result.BinaryData.Identifier.assign(temp.data(), temp.data() + temp.size());
+ return result;
+ }
+ else
+ qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << id << "does not contain a valid byte string identifier";
+ break;
+ }
+ default:
+ qCWarning(QT_OPCUA_PLUGINS_FREEOPCUA) << "Could not parse node id:" << id;
+ }
+ return OpcUa::NodeId();
+}
+
}
QT_END_NAMESPACE
diff --git a/src/plugins/opcua/freeopcua/qfreeopcuavalueconverter.h b/src/plugins/opcua/freeopcua/qfreeopcuavalueconverter.h
index 13fb368..0c6962e 100644
--- a/src/plugins/opcua/freeopcua/qfreeopcuavalueconverter.h
+++ b/src/plugins/opcua/freeopcua/qfreeopcuavalueconverter.h
@@ -56,6 +56,7 @@ namespace QFreeOpcUaValueConverter
QVariant toQVariant(const OpcUa::Variant &variant);
OpcUa::Variant toTypedVariant(const QVariant &variant, QOpcUa::Types type);
QString nodeIdToString(const OpcUa::NodeId &id);
+ OpcUa::NodeId stringToNodeId(const QString &id);
QOpcUa::UaStatusCode exceptionToStatusCode(const std::exception &ex);