You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2023/09/25 05:58:41 UTC
[plc4x] branch develop updated: fix(plc4j/opcua): Fix incorrectly handled GUID tags (#1099)
This is an automated email from the ASF dual-hosted git repository.
sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/develop by this push:
new bd064a5944 fix(plc4j/opcua): Fix incorrectly handled GUID tags (#1099)
bd064a5944 is described below
commit bd064a594440160d98da61e6eae741fa2777a263
Author: takraj <ta...@gmail.com>
AuthorDate: Mon Sep 25 07:58:36 2023 +0200
fix(plc4j/opcua): Fix incorrectly handled GUID tags (#1099)
1. The driver tried to `arraycopy()` a `Long`, which caused `ArrayStoreException`.
2. GUIDs are structured objects, that matters when it comes to byte ordering.
The OPC-UA protocol uses little (mixed) endian GUID encoding format, while Java
uses the standard big endian one (RFC4122), so conversion is needed.
References:
* https://reference.opcfoundation.org/Core/Part6/v104/docs/5.2.2.6
* https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding
* https://devblogs.microsoft.com/oldnewthing/20220928-00/?p=107221
* https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html
* https://www.ietf.org/rfc/rfc4122.txt
---
.../java/opcua/protocol/OpcuaProtocolLogic.java | 13 +++--
.../plc4x/java/opcua/ManualOpcuaGuidTag.java | 43 +++++++++++++++
.../opcua/protocol/OpcuaProtocolLogicTest.java | 63 ++++++++++++++++++++++
3 files changed, 115 insertions(+), 4 deletions(-)
diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
index fb320c26d9..543db9acbc 100644
--- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
+++ b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogic.java
@@ -18,6 +18,7 @@
*/
package org.apache.plc4x.java.opcua.protocol;
+import java.nio.ByteBuffer;
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.messages.*;
import org.apache.plc4x.java.api.model.PlcConsumerRegistration;
@@ -228,10 +229,14 @@ public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements H
nodeId = new NodeId(new NodeIdNumeric((short) tag.getNamespace(), Long.parseLong(tag.getIdentifier())));
} else if (tag.getIdentifierType() == OpcuaIdentifierType.GUID_IDENTIFIER) {
UUID guid = UUID.fromString(tag.getIdentifier());
- byte[] guidBytes = new byte[16];
- System.arraycopy(guid.getMostSignificantBits(), 0, guidBytes, 0, 8);
- System.arraycopy(guid.getLeastSignificantBits(), 0, guidBytes, 8, 8);
- nodeId = new NodeId(new NodeIdGuid((short) tag.getNamespace(), guidBytes));
+ ByteBuffer bb = ByteBuffer.allocate(16)
+ .order(java.nio.ByteOrder.LITTLE_ENDIAN)
+ .putInt((int)(guid.getMostSignificantBits() >> (4*8)))
+ .putShort((short)(guid.getMostSignificantBits() >> (2*8)))
+ .putShort((short)guid.getMostSignificantBits())
+ .order(java.nio.ByteOrder.BIG_ENDIAN)
+ .putLong(guid.getLeastSignificantBits());
+ nodeId = new NodeId(new NodeIdGuid((short) tag.getNamespace(), bb.array()));
} else if (tag.getIdentifierType() == OpcuaIdentifierType.STRING_IDENTIFIER) {
nodeId = new NodeId(new NodeIdString((short) tag.getNamespace(), new PascalString(tag.getIdentifier())));
}
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualOpcuaGuidTag.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualOpcuaGuidTag.java
new file mode 100644
index 0000000000..1ab29c5519
--- /dev/null
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/ManualOpcuaGuidTag.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.opcua;
+
+import org.apache.plc4x.java.DefaultPlcDriverManager;
+import org.apache.plc4x.java.api.PlcConnection;
+import org.apache.plc4x.java.api.messages.PlcReadRequest;
+import org.apache.plc4x.java.api.messages.PlcReadResponse;
+
+public class ManualOpcuaGuidTag {
+
+ public static void main(String... args) throws Exception {
+ DefaultPlcDriverManager driverManager = new DefaultPlcDriverManager();
+ try (PlcConnection opcuaConnection = driverManager.getConnection("opcua:tcp://opcuaserver.com:48010")) {
+ PlcReadRequest request = opcuaConnection.readRequestBuilder()
+ .addTagAddress(
+ "VariableWithGuidNodeId",
+ "ns=2;g=5CE9DBCE-5D79-434C-9AC3-1CFBA9A6E92C"
+ )
+ .build();
+
+ PlcReadResponse response = request.execute().get();
+ System.out.println(response.getObject("VariableWithGuidNodeId"));
+ }
+ }
+}
diff --git a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogicTest.java b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogicTest.java
new file mode 100644
index 0000000000..5a7694c402
--- /dev/null
+++ b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/protocol/OpcuaProtocolLogicTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.plc4x.java.opcua.protocol;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.plc4x.java.opcua.readwrite.NodeId;
+import org.apache.plc4x.java.opcua.readwrite.NodeIdGuid;
+import org.apache.plc4x.java.opcua.readwrite.NodeIdType;
+import org.apache.plc4x.java.opcua.tag.OpcuaTag;
+import org.junit.jupiter.api.Test;
+
+public class OpcuaProtocolLogicTest {
+
+ @Test
+ public void testGenerateNodeId() {
+ OpcuaTag tag = OpcuaTag.of("ns=2;g=00112233-4455-6677-8899-aabbccddeeff");
+ NodeId nodeId = OpcuaProtocolLogic.generateNodeId(tag);
+ assertEquals(NodeIdType.nodeIdTypeGuid, nodeId.getNodeId().getNodeType());
+
+ NodeIdGuid nodeIdGuid = (NodeIdGuid) nodeId.getNodeId();
+ assertEquals(2, nodeIdGuid.getNamespaceIndex());
+ assertArrayEquals(
+ new byte[] {
+ (byte) 0x33,
+ (byte) 0x22,
+ (byte) 0x11,
+ (byte) 0x00,
+ (byte) 0x55,
+ (byte) 0x44,
+ (byte) 0x77,
+ (byte) 0x66,
+ (byte) 0x88,
+ (byte) 0x99,
+ (byte) 0xaa,
+ (byte) 0xbb,
+ (byte) 0xcc,
+ (byte) 0xdd,
+ (byte) 0xee,
+ (byte) 0xff
+ },
+ nodeIdGuid.getId()
+ );
+ }
+}