This is an automated email from the ASF dual-hosted git repository.
hutcheb pushed a commit to branch feature/native_opua_client
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/feature/native_opua_client by
this push:
new f423f0a Working on CreateSessionResponse Parsing.
f423f0a is described below
commit f423f0a26e1ece7f073c931f25c205589a2f3cf4
Author: hutcheb <[email protected]>
AuthorDate: Wed Dec 30 20:24:54 2020 -0500
Working on CreateSessionResponse Parsing.
Almost finished with the connection messages.
---
.../language/java/JavaLanguageTemplateHelper.java | 2 +-
.../resources/templates/java/pojo-template.ftlh | 8 +-
.../mspec/parser/MessageFormatListener.java | 4 +-
.../apache/plc4x/java/opcua/OpcuaPlcDriver.java | 8 +-
.../java/opcua/config/OpcuaConfiguration.java | 3 +-
.../java/opcua/protocol/OpcuaProtocolLogic.java | 229 ++++++++-
.../plc4x/java/spi/generation/ReadBuffer.java | 72 ++-
.../plc4x/java/spi/generation/WriteBuffer.java | 5 +-
protocols/opcua/pom.xml | 29 +-
.../src/main/resources/protocols/opcua/opcua.mspec | 74 ++-
protocols/opcua/src/main/xslt/opc-types.xsl | 569 +++++++++++++++++++--
11 files changed, 881 insertions(+), 122 deletions(-)
diff --git
a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index 81081da..fa7e36f 100644
---
a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++
b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -412,7 +412,7 @@ public class JavaLanguageTemplateHelper extends
BaseFreemarkerLanguageTemplateHe
}
case STRING: {
StringTypeReference stringTypeReference =
(StringTypeReference) simpleTypeReference;
- return "io.writeString(" + stringTypeReference.getSizeInBits()
+ ", \"" +
+ return "io.writeString(" + stringTypeReference.getLength() +
", \"" +
stringTypeReference.getEncoding() + "\", (String) " +
fieldName + ")";
}
}
diff --git
a/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh
b/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh
index 822c7f8..7772377 100644
---
a/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh
+++
b/build-utils/language-java/src/main/resources/templates/java/pojo-template.ftlh
@@ -204,8 +204,14 @@ public<#if helper.isDiscriminatedParentTypeDefinition()>
abstract</#if> class ${
<#assign discriminatorField = field>
<#assign simpleTypeReference = discriminatorField.type>
- // Discriminator Field (${discriminatorField.name})
+ // Discriminator Field (${discriminatorField.name})
+ <#if
helper.getLanguageTypeNameForTypeReference(discriminatorField.type) = "String">
+ <#assign simpleTypeReference = discriminatorField.type>
+ lengthInBits += ${simpleTypeReference.getLength()};
+ <#else>
+ <#assign simpleTypeReference = discriminatorField.type>
lengthInBits += ${simpleTypeReference.sizeInBits};
+ </#if>
<#break>
<#case "enum">
<#assign enumField = field>
diff --git
a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
index 0759877..d0b80c1 100644
---
a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
+++
b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/parser/MessageFormatListener.java
@@ -436,8 +436,8 @@ public class MessageFormatListener extends
MSpecBaseListener {
SimpleTypeReference.SimpleBaseType simpleBaseType =
SimpleTypeReference.SimpleBaseType.valueOf(ctx.base.getText().toUpperCase());
// String types need an additional "encoding" field and an optional
size.
- if(simpleBaseType == SimpleTypeReference.SimpleBaseType.STRING) {
- String size = (ctx.length != null) ?
ctx.length.getText().substring( 1, ctx.length.getText().length() - 1 ) : "-1";
+ if(simpleBaseType == SimpleTypeReference.SimpleBaseType.STRING) {
+ String size = ctx.length.getText().substring( 1,
ctx.length.getText().length() - 1 );
String encoding = (ctx.encoding != null) ? ctx.encoding.getText()
: "UTF-8";
return new DefaultStringTypeReference(simpleBaseType, size,
encoding);
}
diff --git
a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
index cb1e8ef..b2c7d1f 100644
---
a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
+++
b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
@@ -121,7 +121,7 @@ public class OpcuaPlcDriver extends
GeneratedDriverBase<OpcuaAPU> {
protected ProtocolStackConfigurer<OpcuaAPU> getStackConfigurer() {
return SingleProtocolStackConfigurer.builder(OpcuaAPU.class,
OpcuaAPUIO.class)
.withProtocol(OpcuaProtocolLogic.class)
- //.withPacketSizeEstimator(ByteLengthEstimator.class)
+ .withPacketSizeEstimator(ByteLengthEstimator.class)
// Every incoming message is to be treated as a response.
.withParserArgs(true)
.littleEndian()
@@ -131,9 +131,9 @@ public class OpcuaPlcDriver extends
GeneratedDriverBase<OpcuaAPU> {
/** Estimate the Length of a Packet */
public static class ByteLengthEstimator implements ToIntFunction<ByteBuf> {
@Override
- public int applyAsInt(ByteBuf byteBuf) {
- if (byteBuf.readableBytes() >= 6) {
- return byteBuf.getUnsignedShort(byteBuf.readerIndex() + 256) +
6;
+ public int applyAsInt(ByteBuf byteBuf) {
+ if (byteBuf.readableBytes() >= 8) {
+ return
Integer.reverseBytes(byteBuf.getInt(byteBuf.readerIndex() + 4));
}
return -1;
}
diff --git
a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java
b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java
index bff0452..07f1b47 100644
---
a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java
+++
b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/config/OpcuaConfiguration.java
@@ -25,8 +25,7 @@ import
org.apache.plc4x.java.spi.configuration.annotations.defaults.IntDefaultVa
import org.apache.plc4x.java.transport.tcp.TcpTransportConfiguration;
public class OpcuaConfiguration implements Configuration,
TcpTransportConfiguration {
-
-
+
@Override
public int getDefaultPort() {
return 12687;
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 cc8be66..4b5593d 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
@@ -32,11 +32,13 @@ import org.apache.plc4x.java.api.types.PlcResponseCode;
import org.apache.plc4x.java.spi.values.PlcNull;
import org.apache.plc4x.java.api.value.PlcValue;
import org.apache.plc4x.java.spi.values.IEC61131ValueHandler;
+import org.apache.plc4x.java.opcua.config.OpcuaConfiguration;
import org.apache.plc4x.java.opcua.readwrite.*;
import org.apache.plc4x.java.opcua.readwrite.io.*;
import org.apache.plc4x.java.opcua.readwrite.types.*;
import org.apache.plc4x.java.spi.ConversationContext;
import org.apache.plc4x.java.spi.Plc4xProtocolBase;
+import org.apache.plc4x.java.spi.configuration.HasConfiguration;
import org.apache.plc4x.java.spi.context.DriverContext;
import org.apache.plc4x.java.spi.generation.ParseException;
import org.apache.plc4x.java.spi.generation.ReadBuffer;
@@ -66,7 +68,7 @@ import java.nio.charset.StandardCharsets;
* So we need to limit those.
* Thus, each request goes to a Work Queue and this Queue ensures, that only 3
are open at the same time.
*/
-public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> {
+public class OpcuaProtocolLogic extends Plc4xProtocolBase<OpcuaAPU> implements
HasConfiguration<OpcuaConfiguration> {
private static final Logger LOGGER =
LoggerFactory.getLogger(OpcuaProtocolLogic.class);
public static final Duration REQUEST_TIMEOUT = Duration.ofMillis(10000);
@@ -75,6 +77,10 @@ public class OpcuaProtocolLogic extends
Plc4xProtocolBase<OpcuaAPU> {
private RequestTransactionManager tm;
@Override
+ public void setConfiguration(OpcuaConfiguration configuration) {
+ }
+
+ @Override
public void close(ConversationContext<OpcuaAPU> context) {
// Nothing to do here ...
}
@@ -84,7 +90,15 @@ public class OpcuaProtocolLogic extends
Plc4xProtocolBase<OpcuaAPU> {
// Only the TCP transport supports login.
LOGGER.info("Opcua Driver running in ACTIVE mode.");
- OpcuaHelloRequest hello = new OpcuaHelloRequest("F", 63, 0, 65535,
65535, 2097152, 64, 31, new String("opc.tcp://127.0.0.1:12687/plc4x"));
+ final String endpoint = "opc.tcp://127.0.0.1:12687/plc4x";
+ OpcuaHelloRequest hello = new OpcuaHelloRequest("F",
+ 0,
+ 65535,
+ 65535,
+ 2097152,
+ 64,
+ endpoint.length(),
+ endpoint);
context.sendRequest(new OpcuaAPU(hello))
.expectResponse(OpcuaAPU.class, REQUEST_TIMEOUT)
@@ -93,16 +107,213 @@ public class OpcuaProtocolLogic extends
Plc4xProtocolBase<OpcuaAPU> {
.handle(opcuaAcknowledgeResponse -> {
LOGGER.debug("Got Hello Response Connection Response");
- OpcuaMessage openMessage = new OpcuaMessage("F", 63, 0, 65535,
65535, 2097152, 64, 31, new String("opc.tcp://127.0.0.1:12687/plc4x"));
- OpcuaOpenRequest openrequest = new OpcuaOpenRequest("F", 63,
0, 65535, 65535, 2097152, 64, 31, new
String("opc.tcp://127.0.0.1:12687/plc4x"));
+ NodeIdTwoByte authenticationToken = new
NodeIdTwoByte(NodeIdType.nodeIdTypeTwoByte,
+ new
TwoByteNodeId((short) 0));
+
+ ExpandedNodeId expandedNodeId = new
ExpandedNodeIdFourByte(NodeIdType.nodeIdTypeFourByte,
+ false,
+ false,
+ new
FourByteNodeId((short) 0, 466),
+ new
PascalString(-1,""),
+ 1L);
+
+ ExpandedNodeId extExpandedNodeId = new
ExpandedNodeIdTwoByte(NodeIdType.nodeIdTypeTwoByte,
+ false,
+ false,
+ new
TwoByteNodeId((short) 0),
+ null,
+ null);
+
+ ExtensionObject extObject = new
ExtensionObject(extExpandedNodeId, (short) 0);
+
+ RequestHeader requestHeader = new
RequestHeader(authenticationToken,
+
System.currentTimeMillis() * 10000L,
+ 0L,
+ 0L,
+ new
PascalString(-1, ""),
+ 10000L,
+ extObject);
+
+
+
+ OpenSecureChannelRequest openrequest = new
OpenSecureChannelRequest((byte) 1,
+ (byte) 0,
+ requestHeader,
+ 0L,
+
SecurityTokenRequestType.securityTokenRequestTypeIssue,
+
MessageSecurityMode.messageSecurityModeNone,
+ new
PascalString(-1, ""),
+ 36000000);
- context.sendRequest(new OpcuaAPU(hello))
+ String nameSpace =
"http://opcfoundation.org/UA/SecurityPolicy#None";
+ OpcuaOpenRequest openRequest = new OpcuaOpenRequest("F",
+ 0,
+
nameSpace.length(),
+ nameSpace,
+ -1,
+ "",
+ -1,
+ "",
+ 1,
+ 1,
+ openrequest);
+
+ context.sendRequest(new OpcuaAPU(openRequest))
.expectResponse(OpcuaAPU.class, REQUEST_TIMEOUT)
- .check(p -> p.getMessage() instanceof
OpcuaAcknowledgeResponse)
- .unwrap(p -> (OpcuaAcknowledgeResponse) p.getMessage())
- .handle(opcuaAcknowledgeResponse -> {
- LOGGER.debug("Got Hello Response Connection Response");
+ .check(p -> p.getMessage() instanceof OpcuaOpenResponse)
+ .unwrap(p -> (OpcuaOpenResponse) p.getMessage())
+ .handle(opcuaOpenResponse -> {
+ LOGGER.debug("Got Secure Response Connection
Response");
+ OpenSecureChannelResponse openSecureChannelResponse =
(OpenSecureChannelResponse) opcuaOpenResponse.getMessage();
+ Integer tokenId = (int)
openSecureChannelResponse.getSecurityToken().getTokenId();
+ Integer channelId = (int)
openSecureChannelResponse.getSecurityToken().getChannelId();
+ Integer nextSequenceNumber =
opcuaOpenResponse.getSequenceNumber() + 1;
+ Integer nextRequestId =
opcuaOpenResponse.getRequestId() + 1;
+
+ NodeIdTwoByte authenticationToken2 = new
NodeIdTwoByte(NodeIdType.nodeIdTypeTwoByte,
+
new TwoByteNodeId((short) 0));
+
+ ExpandedNodeId extExpandedNodeId2 = new
ExpandedNodeIdTwoByte(NodeIdType.nodeIdTypeTwoByte,
+
false,
+
false,
+
new TwoByteNodeId((short) 0),
+
null,
+
null);
+
+ ExtensionObject extObject2 = new
ExtensionObject(extExpandedNodeId2, (short) 0);
+
+ RequestHeader requestHeader2 = new
RequestHeader(authenticationToken2,
+
System.currentTimeMillis() * 10000L,
+ 0L,
+ 0L,
+ new
PascalString(-1, ""),
+ 10000L,
+
extObject2);
+
+ String applicationUri =
"urn:eclipse:milo:plc4x:client";
+ String productUri = "urn:eclipse:milo:plc4x:client";
+ String text = "eclipse milo opc-ua client of the
apache PLC4X:PLC4J project";
+ LocalizedText applicationName = new
LocalizedText((short) 0,
+ true,
+ true,
+ new
PascalString(2, "en"),
+ new
PascalString(text.length(), text));
+ PascalString gatewayServerUri = new PascalString(-1,
"");
+ PascalString discoveryProfileUri = new
PascalString(-1, "");
+ int noOfDiscoveryUrls = -1;
+ PascalString discoveryUrls = null;
+
+ ApplicationDescription clientDescription = new
ApplicationDescription(new PascalString(applicationUri.length(),
applicationUri),
+
new PascalString(productUri.length(), productUri),
+
applicationName,
+
ApplicationType.applicationTypeClient,
+
gatewayServerUri,
+
discoveryProfileUri,
+
noOfDiscoveryUrls,
+
discoveryUrls);
+
+ String endpoint2 = "opc.tcp://127.0.0.1:12687/plc4x";
+ String sessionName = "UaSession:eclipse milo opc-ua
client of the apache PLC4X:PLC4J project:" + System.currentTimeMillis();
+ String clientNonce = "764287368237654873259869867";
+
+ CreateSessionRequest createSessionRequest = new
CreateSessionRequest((byte) 1,
+ (byte)
0,
+
requestHeader2,
+
clientDescription,
+ new
PascalString(-1, ""),
+ new
PascalString(endpoint2.length(), endpoint2),
+ new
PascalString(sessionName.length(), sessionName),
+ new
PascalString(clientNonce.length(), clientNonce),
+ new
PascalString(-1, ""),
+
120000L,
+ 0L);
+
+ OpcuaMessageRequest messageRequest = new
OpcuaMessageRequest("F",
+
channelId,
+
tokenId,
+
nextSequenceNumber,
+
nextRequestId,
+
createSessionRequest);
+
+ context.sendRequest(new OpcuaAPU(messageRequest))
+ .expectResponse(OpcuaAPU.class, REQUEST_TIMEOUT)
+ .check(p -> p.getMessage() instanceof
OpcuaMessageResponse)
+ .unwrap(p -> (OpcuaMessageResponse) p.getMessage())
+ .handle(opcuaMessageResponse -> {
+ LOGGER.debug("Got Create Session Response
Connection Response");
+ CreateSessionResponse createSessionResponse =
(CreateSessionResponse) opcuaMessageResponse.getMessage();
+
+ NodeIdTwoByte authenticationToken3 =
(NodeIdTwoByte) createSessionResponse.getAuthenticationToken();
+ Integer tokenId2 = (int)
opcuaMessageResponse.getSecureTokenId();
+ Integer channelId2 = (int)
opcuaMessageResponse.getSecureChannelId();
+ Integer nextSequenceNumber2 =
opcuaMessageResponse.getSequenceNumber() + 1;
+ Integer nextRequestId2 =
opcuaMessageResponse.getRequestId() + 1;
+
+
+ ExpandedNodeId extExpandedNodeId3 = new
ExpandedNodeIdTwoByte(NodeIdType.nodeIdTypeTwoByte,
+
false,
+
false,
+
new TwoByteNodeId((short) 0),
+
null,
+
null);
+
+ ExtensionObject extObject3 = new
ExtensionObject(extExpandedNodeId3, (short) 0);
+
+ RequestHeader requestHeader3 = new
RequestHeader(authenticationToken3,
+
System.currentTimeMillis() * 10000L,
+
1L,
+
0L,
+
new PascalString(-1, ""),
+
10000L,
+
extObject3);
+
+ SignatureData clientSignature = new
SignatureData(new PascalString(-1, ""), new PascalString(-1, ""));
+
+ SignedSoftwareCertificate[]
signedSoftwareCertificate = null;
+
+ ExpandedNodeId extExpandedNodeId4 = new
ExpandedNodeIdFourByte(NodeIdType.nodeIdTypeFourByte,
+
false,
+
false,
+
new FourByteNodeId((short) 0, 321),
+
null,
+
null);
+
+
+ ExtensionObject useridentityToken = new
ExtensionObject(extExpandedNodeId4, (short) 0);
+
+ String endpoint3 =
"opc.tcp://127.0.0.1:12687/plc4x";
+
+ ActivateSessionRequest activateSessionRequest
= new ActivateSessionRequest((byte) 1,
+
(byte) 0,
+
requestHeader3,
+
clientSignature,
+
0,
+
signedSoftwareCertificate,
+
0,
+
null,
+
useridentityToken,
+
clientSignature);
+
+ OpcuaMessageRequest activateMessageRequest =
new OpcuaMessageRequest("F",
+
channelId2,
+
tokenId2,
+
nextSequenceNumber2,
+
nextRequestId2,
+
activateSessionRequest);
+
+ context.sendRequest(new
OpcuaAPU(activateMessageRequest))
+ .expectResponse(OpcuaAPU.class,
REQUEST_TIMEOUT)
+ .check(p -> p.getMessage() instanceof
OpcuaMessageResponse)
+ .unwrap(p -> (OpcuaMessageResponse)
p.getMessage())
+ .handle(opcuaActivateResponse -> {
+ LOGGER.debug("Got Activate Session
Response Connection Response");
+
+ });
+
+
+ });
+
});
});
}
diff --git
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
index 9635c3a..b534ec2 100644
---
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
+++
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java
@@ -28,8 +28,13 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.Charset;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
public class ReadBuffer {
+ private static final Logger LOGGER =
LoggerFactory.getLogger(ReadBuffer.class);
+
private final MyDefaultBitInput bi;
private final boolean littleEndian;
private final long totalBytes;
@@ -39,6 +44,7 @@ public class ReadBuffer {
}
public ReadBuffer(byte[] input, boolean littleEndian) {
+ LOGGER.info("Creating read buffer " + input.length)
ArrayByteInput abi = new ArrayByteInput(input);
this.bi = new MyDefaultBitInput(abi);
this.littleEndian = littleEndian;
@@ -82,7 +88,9 @@ public class ReadBuffer {
public boolean readBit() throws ParseException {
try {
- return bi.readBoolean();
+ boolean ret = bi.readBoolean();
+ LOGGER.info("Reading Bit:- " + ret);
+ return ret;
} catch (IOException e) {
throw new ParseException("Error reading", e);
}
@@ -96,7 +104,9 @@ public class ReadBuffer {
throw new ParseException("unsigned byte can only contain max 4
bits");
}
try {
- return bi.readByte(true, bitLength);
+ byte ret = bi.readByte(true, bitLength);
+ LOGGER.info("Reading Unsigned Byte:- " + ret);
+ return ret;
} catch (IOException e) {
throw new ParseException("Error reading", e);
}
@@ -111,7 +121,9 @@ public class ReadBuffer {
}
try {
// No need to flip here as we're only reading one byte.
- return bi.readShort(true, bitLength);
+ short ret = bi.readShort(true, bitLength);
+ LOGGER.info("Reading Unsigned Short:- " + ret);
+ return ret;
} catch (IOException e) {
throw new ParseException("Error reading", e);
}
@@ -127,9 +139,13 @@ public class ReadBuffer {
try {
if (littleEndian) {
int intValue = bi.readInt(true, bitLength);
- return Integer.reverseBytes(intValue) >>> 16;
+ int ret = Integer.reverseBytes(intValue) >>> 16;
+ LOGGER.info("Reading Unsigned Int:- " + ret);
+ return ret;
}
- return bi.readInt(true, bitLength);
+ int ret = bi.readInt(true, bitLength);
+ LOGGER.info("Reading Unsigned Int:- " + ret);
+ return ret;
} catch (IOException e) {
throw new ParseException("Error reading", e);
}
@@ -145,9 +161,13 @@ public class ReadBuffer {
try {
if (littleEndian) {
final long longValue = bi.readLong(true, bitLength);
- return Long.reverseBytes(longValue) >>> 32;
+ long ret = Long.reverseBytes(longValue) >>> 32;
+ LOGGER.info("Reading Unsigned Long:- " + ret);
+ return ret;
}
- return bi.readLong(true, bitLength);
+ long ret = bi.readLong(true, bitLength);
+ LOGGER.info("Reading Unsigned Long:- " + ret);
+ return ret;
} catch (IOException e) {
throw new ParseException("Error reading", e);
}
@@ -186,7 +206,9 @@ public class ReadBuffer {
throw new ParseException("byte can only contain max 8 bits");
}
try {
- return bi.readByte(false, bitLength);
+ byte ret = bi.readByte(false, bitLength);
+ LOGGER.info("Reading Byte:- " + ret);
+ return ret;
} catch (IOException e) {
throw new ParseException("Error reading", e);
}
@@ -201,9 +223,13 @@ public class ReadBuffer {
}
try {
if (littleEndian) {
- return Short.reverseBytes(bi.readShort(false, bitLength));
+ short ret = Short.reverseBytes(bi.readShort(false,
bitLength));
+ LOGGER.info("Reading Short:- " + ret);
+ return ret;
}
- return bi.readShort(false, bitLength);
+ short ret = bi.readShort(false, bitLength);
+ LOGGER.info("Reading Short:- " + ret);
+ return ret;
} catch (IOException e) {
throw new ParseException("Error reading", e);
}
@@ -218,9 +244,13 @@ public class ReadBuffer {
}
try {
if (littleEndian) {
- return Integer.reverseBytes(bi.readInt(false, bitLength));
+ int ret = Integer.reverseBytes(bi.readInt(false, bitLength));
+ LOGGER.info("Reading Integer:- " + ret);
+ return ret;
}
- return bi.readInt(false, bitLength);
+ int ret = bi.readInt(false, bitLength);
+ LOGGER.info("Reading Int:- " + ret);
+ return ret;
} catch (IOException e) {
throw new ParseException("Error reading", e);
}
@@ -235,9 +265,13 @@ public class ReadBuffer {
}
try {
if (littleEndian) {
- return Long.reverseBytes(bi.readLong(false, bitLength));
+ long ret = Long.reverseBytes(bi.readLong(false, bitLength));
+ LOGGER.info("Reading Read Long:- " + ret);
+ return ret;
}
- return bi.readLong(false, bitLength);
+ long ret = bi.readLong(false, bitLength);
+ LOGGER.info("Reading Read Long:- " + ret);
+ return ret;
} catch (IOException e) {
throw new ParseException("Error reading", e);
}
@@ -285,7 +319,9 @@ public class ReadBuffer {
public double readDouble(int bitLength) throws ParseException {
if(bitLength == 64) {
long longValue = readLong(64);
- return Double.longBitsToDouble(longValue);
+ double ret = Double.longBitsToDouble(longValue);
+ LOGGER.info("Reading Double:- " + ret);
+ return ret;
} else {
throw new UnsupportedOperationException("unsupported bit length
(only 64 supported)");
}
@@ -298,14 +334,16 @@ public class ReadBuffer {
public String readString(int bitLength, String encoding) {
byte[] strBytes = new byte[bitLength / 8];
for (int i = 0; (i < (bitLength / 8)) && hasMore(8); i++) {
- try {
+ try {
strBytes[i] = readByte(8);
} catch (Exception e) {
throw new PlcRuntimeException(e);
}
}
//replaceAll function removes and leading ' char or hypens.
- return new String(strBytes,
Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]","")));
+ String ret = new String(strBytes,
Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]","")));
+ LOGGER.info("Reading String:- " + ret);
+ return ret;
}
}
diff --git
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
index a4424cf..1f6fa85 100644
---
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
+++
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java
@@ -190,7 +190,7 @@ public class WriteBuffer {
}
}
- public void writeInt(int bitLength, int value) throws ParseException {
+ public void writeInt(int bitLength, int value) throws ParseException {
if(bitLength <= 0) {
throw new ParseException("int must contain at least 1 bit");
}
@@ -257,8 +257,7 @@ public class WriteBuffer {
final byte[] bytes = value.getBytes(Charset.forName(encoding));
try {
int count = 0;
- for (byte aByte : bytes) {
- System.out.println(count);
+ for (byte aByte : bytes) {
count += 1;
bo.writeByte(false, 8, aByte);
}
diff --git a/protocols/opcua/pom.xml b/protocols/opcua/pom.xml
index ecfa277..aeb3acb 100644
--- a/protocols/opcua/pom.xml
+++ b/protocols/opcua/pom.xml
@@ -55,6 +55,25 @@
</executions>
</plugin>
<plugin>
+ <groupId>com.googlecode.maven-download-plugin</groupId>
+ <artifactId>download-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>fetch-opc-discriminators</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>wget</goal>
+ </goals>
+ <configuration>
+
<url>https://opcfoundation.org/UA/schemas/1.04/Opc.Ua.NodeSet2.Services.xml</url>
+ <unpack>false</unpack>
+
<outputDirectory>${project.build.directory}/downloads</outputDirectory>
+ <outputFileName>opc-discriminators.xml</outputFileName>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
<version>1.0.2</version>
@@ -70,7 +89,7 @@
<transformationSets>
<transformationSet>
<dir>${project.build.directory}/downloads</dir>
- <includes>*.xml</includes>
+ <includes>opc-datatypes.xml</includes>
<stylesheet>src/main/xslt/opc-types.xsl</stylesheet>
<outputDir>${project.build.outputDirectory}/protocols/opcua</outputDir>
<fileMappers>
@@ -78,6 +97,12 @@
<targetExtension>.mspec</targetExtension>
</fileMapper>
</fileMappers>
+ <parameters>
+ <parameter>
+ <name>services</name>
+
<value>${project.build.directory}/downloads/opc-discriminators.xml</value>
+ </parameter>
+ </parameters>
<outputProperties>
<outputProperty>
<name>indent</name>
@@ -86,7 +111,7 @@
</outputProperties>
</transformationSet>
</transformationSets>
- </configuration>
+ </configuration>
</plugin>
</plugins>
</build>
diff --git a/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec
b/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec
index 85cc054..d4406bf 100644
--- a/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec
+++ b/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec
@@ -27,15 +27,15 @@
[discriminator string '24' 'messageType']
[typeSwitch 'messageType','response'
['HEL','false' OpcuaHelloRequest
- [simple string '8' 'chunk']
- [simple int 32 'messageSize']
+ [simple string '1 * 8' 'chunk']
+ [implicit int 32 'messageSize'
'lengthInBytes']
[simple int 32 'version']
[simple int 32 'receiveBufferSize']
[simple int 32 'sendBufferSize']
[simple int 32 'maxMessageSize']
[simple int 32 'maxChunkCount']
[simple int 32 'stringLength']
- [simple string 'stringLength' 'endpoint']
+ [simple string 'stringLength * 8' 'endpoint']
]
['HEL','true' OpcuaHelloResponse
]
@@ -43,7 +43,7 @@
]
['ACK','true' OpcuaAcknowledgeResponse
[simple string '8' 'chunk']
- [simple int 32 'messageSize']
+ [implicit int 32 'messageSize'
'lengthInBytes']
[simple int 32 'version']
[simple int 32 'receiveBufferSize']
[simple int 32 'sendBufferSize']
@@ -56,63 +56,57 @@
]
['OPN','false' OpcuaOpenRequest
[simple string '8' 'chunk']
- [simple int 32 'messageSize']
+ [implicit int 32 'messageSize'
'lengthInBytes']
[simple int 32 'secureChannelId']
[simple int 32 'securityPolicyUriSize']
- [simple string 'securityPolicyUriSize == -1 ? 0 :
securityPolicyUriSize' 'endpoint']
+ [simple string 'securityPolicyUriSize == -1 ? 0 :
securityPolicyUriSize * 8' 'endpoint']
[simple int 32 'senderCertificateSize']
- [simple string 'senderCertificateSize == -1 ? 0 :
senderCertificateSize' 'senderCertificate']
+ [simple string 'senderCertificateSize == -1 ? 0 :
senderCertificateSize * 8' 'senderCertificate']
[simple int 32
'receiverCertificateThumbprintSize']
- [simple string 'receiverCertificateThumbprintSize == -1 ?
0 : receiverCertificateThumbprintSize'
'receiverCertificateThumbprint']
+ [simple string 'receiverCertificateThumbprintSize == -1 ?
0 : receiverCertificateThumbprintSize * 8'
'receiverCertificateThumbprint']
[simple int 32 'sequenceNumber']
[simple int 32 'requestId']
[simple OpcuaMessage 'message']
]
['OPN','true' OpcuaOpenResponse
+ [simple string '8' 'chunk']
+ [implicit int 32 'messageSize' 'lengthInBytes']
+ [simple int 32 'secureChannelId']
+ [simple int 32 'securityPolicyUriSize']
+ [simple string 'securityPolicyUriSize == -1 ? 0 :
securityPolicyUriSize * 8' 'endpoint']
+ [simple int 32 'senderCertificateSize']
+ [simple string 'senderCertificateSize == -1 ? 0 :
senderCertificateSize * 8' 'senderCertificate']
+ [simple int 32
'receiverCertificateThumbprintSize']
+ [simple string 'receiverCertificateThumbprintSize == -1 ?
0 : receiverCertificateThumbprintSize * 8'
'receiverCertificateThumbprint']
+ [simple int 32 'sequenceNumber']
+ [simple int 32 'requestId']
+ [simple OpcuaMessage 'message']
]
['CLO','false' OpcuaCloseRequest
]
['CLO','true' OpcuaCloseResponse
]
['MSG','false' OpcuaMessageRequest
+ [simple string '8' 'chunk']
+ [implicit int 32 'messageSize' 'lengthInBytes']
+ [simple int 32 'secureChannelId']
+ [simple int 32 'secureTokenId']
+ [simple int 32 'sequenceNumber']
+ [simple int 32 'requestId']
+ [simple OpcuaMessage 'message']
]
['MSG','true' OpcuaMessageResponse
+ [simple string '8' 'chunk']
+ [implicit int 32 'messageSize' 'lengthInBytes']
+ [simple int 32 'secureChannelId']
+ [simple int 32 'secureTokenId']
+ [simple int 32 'sequenceNumber']
+ [simple int 32 'requestId']
+ [simple OpcuaMessage 'message']
]
]
]
-[discriminatedType 'OpcuaMessage'
- [simple int 8 'nodeIdEncodingMask' ]
- [simple int 8 'nodeIdNamespaceIndex' ]
- [discriminator int 16 'nodeId' ]
- [typeSwitch 'nodeId'
- ['0x01BE' OpcuaOpenSecureChannelRequest
- [simple int 8 'authenticationToken' ]
- [simple int 64 'timestamp' ]
- [simple int 32 'requestHandle' ]
- [simple bit 'serviceLevelSymbolicId' ]
- [simple bit 'serviceLevelLocalizedText' ]
- [simple bit 'serviceLevelAdditionalInfo' ]
- [simple bit 'serviceLevelStatusCode' ]
- [simple bit 'serviceLevelDiagnostics' ]
- [simple bit 'operationLevelSymbolcId' ]
- [simple bit 'operationLevelLocalizedText' ]
- [simple bit 'operationLevelAdditionalInfo' ]
- [simple bit 'operationLevelStatusCode' ]
- [simple bit 'operationLevelDiagnostics' ]
- [reserved int 22 '0x000000'] // padding
- [simple int 32 'auditEntryId' ]
- [simple int 32 'timeoutHint' ]
- [simple int 24 'additionalHeader' ]
- [simple int 32 'clientProtocolVersion' ]
- [simple int 32 'seecurityTokenRequestType' ]
- [simple int 32 'messageSecurityMode' ]
- [simple int 32 'clientNonceSize' ]
- [simple string 'clientNonceSize == -1 ? 0 :
clientNonceSize' 'clientNonce']
- [simple int 32 'requestedLifetime' ]
- ]
- ]
-]
[enum string '-1' 'OpcuaDataType'
['IEC61131_NULL' NULL ]
diff --git a/protocols/opcua/src/main/xslt/opc-types.xsl
b/protocols/opcua/src/main/xslt/opc-types.xsl
index 8ec49e4..a36a514 100644
--- a/protocols/opcua/src/main/xslt/opc-types.xsl
+++ b/protocols/opcua/src/main/xslt/opc-types.xsl
@@ -22,7 +22,8 @@
xmlns:opc="http://opcfoundation.org/BinarySchema/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ua="http://opcfoundation.org/UA/"
- xmlns:tns="http://opcfoundation.org/UA/">
+ xmlns:tns="http://opcfoundation.org/UA/"
+ xmlns:node="http://opcfoundation.org/UA/2011/03/UANodeSet.xsd">
<xsl:output
method="text"
@@ -30,36 +31,532 @@
encoding="utf-8"
/>
- <xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'" />
- <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
+ <xsl:param name="services"></xsl:param>
+
+
+ <xsl:param name="file" select="document($services)"/>
+
+ <xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'"/>
+ <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:template match="/">
-//
-// 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.
-//
- <xsl:apply-templates select="opc:TypeDictionary"/>
+[discriminatedType 'OpcuaMessage'
+ [simple int 8 'OPCUAnodeIdEncodingMask' ]
+ [simple int 8 'OPCUAnodeIdNamespaceIndex' ]
+ [discriminator int 16 'OPCUAnodeId' ]
+ [typeSwitch 'OPCUAnodeId'
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='OpenSecureChannelRequest']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='OpenSecureChannelResponse']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='CreateSessionRequest']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='CreateSessionResponse']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='ActivateSessionRequest']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='ActivateSessionResponse']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='ReadRequest']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='ReadResponse']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='WriteRequest']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='WriteResponse']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='CloseSessionRequest']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='CloseSessionResponse']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='CloseSecureChannelRequest']"/>
+ <xsl:apply-templates
select="$file/node:UANodeSet/node:UADataType[@BrowseName='CloseSecureChannelResponse']"/>
+ ]
+]
+
+[type 'RequestHeader'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='RequestHeader']"/>
+]
+[enum int 32 'SecurityTokenRequestType'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:EnumeratedType[@Name='SecurityTokenRequestType']"/>
+]
+[enum int 32 'MessageSecurityMode'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:EnumeratedType[@Name='MessageSecurityMode']"/>
+]
+[type 'ResponseHeader'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='ResponseHeader']"/>
+]
+[type 'ChannelSecurityToken'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='ChannelSecurityToken']"/>
+]
+
+[type 'DiagnosticInfo'
+ [simple bit 'symbolicIdSpecified']
+ [simple bit 'namespaceURISpecified']
+ [simple bit 'localizedTextSpecified']
+ [simple bit 'localeSpecified']
+ [simple bit 'additionalInfoSpecified']
+ [simple bit 'innerStatusCodeSpecified']
+ [simple bit 'innerDiagnosticInfoSpecified']
+ [simple bit 'reserved1']
+ [optional int 32 'symbolicId' 'symbolicIdSpecified']
+ [optional int 32 'namespaceURI' 'namespaceURISpecified']
+ [optional int 32 'locale' 'localizedTextSpecified']
+ [optional int 32 'localizedText' 'localeSpecified']
+ [optional PascalString 'additionalInfo' 'additionalInfoSpecified']
+ [optional StatusCode 'innerStatusCode' 'innerStatusCodeSpecified']
+ [optional DiagnosticInfo 'innerDiagnosticInfo'
'innerDiagnosticInfoSpecified']
+]
+
+[type 'StatusCode'
+ [simple int 32 'statusCode']
+]
+
+[type 'XmlElement'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='XmlElement']"/>
+]
+
+[type 'DataValue'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='DataValue']"/>
+]
+
+[enum int 6 'NodeIdType'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:EnumeratedType[@Name='NodeIdType']"/>
+]
+
+[type 'TwoByteNodeId'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='TwoByteNodeId']"/>
+]
+
+[type 'FourByteNodeId'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='FourByteNodeId']"/>
+]
+
+[type 'NumericNodeId'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='NumericNodeId']"/>
+]
+
+[type 'StringNodeId'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='StringNodeId']"/>
+]
+
+[type 'GuidNodeId'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='GuidNodeId']"/>
+]
+
+[type 'ByteStringNodeId'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='ByteStringNodeId']"/>
+]
+
+[type 'DataValue'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='DataValue']"/>
+]
+
+[discriminatedType 'Variant'
+ [discriminator uint 6 'VariantType']
+ [typeSwitch 'VariantType'
+ ['1' VariantBoolean
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array bit 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['2' VariantSByte
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array int 8 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['3' VariantByte
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array uint 8 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['4' VariantInt16
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array int 16 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['5' VariantUInt16
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array uint 16 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['6' VariantInt32
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array int 32 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['7' VariantUInt32
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array uint 32 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['8' VariantInt64
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array int 64 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['9' VariantUInt64
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array uint 64 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['10' VariantFloat
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array float 8.23 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['11' VariantDouble
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array float 11.52 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['12' VariantString
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array PascalString 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['13' VariantDateTime
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array int 64 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['14' VariantGuid
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array string '-1' 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['15' VariantByteString
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array PascalString 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['16' VariantXmlElement
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array XmlElement 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['17' VariantNodeId
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array NodeId 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['18' VariantExpandedNodeId
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array ExpandedNodeId 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['19' VariantStatusCode
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array StatusCode 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['20' VariantQualifiedName
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array QualifiedName 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['21' VariantLocalizedText
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array LocalizedText 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['22' VariantExtensionObject
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array ExtensionObject 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['23' VariantDataValue
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array DataValue 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['24' VariantVariant
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array Variant 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ['25' VariantDiagnosticInfo
+
+ [simple bit 'ArrayDimensionsSpecified']
+ [simple bit 'ArrayLengthSpecified']
+ [simple int 32 'arrayLength']
+ [array DiagnosticInfo 'value' count 'arrayLength']
+ [simple int 32 'noOfArrayDimensions']
+ [array bit 'arrayDimensions' count 'noOfArrayDimensions']
+ ]
+ ]
+]
+
+[discriminatedType 'NodeId'
+ [reserved int 2 '0x00']
+ [simple NodeIdType 'nodeIdType']
+ [typeSwitch 'nodeIdType'
+ ['NodeIdType.nodeIdTypeTwoByte' NodeIdTwoByte
+ [simple TwoByteNodeId 'id']
+ ]
+ ['NodeIdType.nodeIdTypeFourByte' NodeIdFourByte
+ [simple FourByteNodeId 'id']
+ ]
+ ['NodeIdType.nodeIdTypeNumeric' NodeIdNumeric
+ [simple NumericNodeId 'id']
+ ]
+ ['NodeIdType.nodeIdTypeString' NodeIdString
+ [simple StringNodeId 'id']
+ ]
+ ['NodeIdType.nodeIdTypeGuid' NodeIdGuid
+ [simple GuidNodeId 'id']
+ ]
+ ['NodeIdType.nodeIdTypeByteString' NodeIdByteString
+ [simple ByteStringNodeId 'id']
+ ]
+ ]
+]
+
+[discriminatedType 'ExpandedNodeId'
+ [simple NodeIdType 'nodeIdType']
+ [typeSwitch 'nodeIdType'
+ ['NodeIdType.nodeIdTypeTwoByte' ExpandedNodeIdTwoByte
+ [simple bit 'serverIndexSpecified']
+ [simple bit 'namespaceURISpecified']
+ [simple TwoByteNodeId 'id']
+ [optional PascalString 'namespaceURI' 'namespaceURISpecified']
+ [optional uint 32 'serverIndex' 'serverIndexSpecified']
+ ]
+ ['NodeIdType.nodeIdTypeFourByte' ExpandedNodeIdFourByte
+ [simple bit 'serverIndexSpecified']
+ [simple bit 'namespaceURISpecified']
+ [simple FourByteNodeId 'id']
+ [optional PascalString 'namespaceURI' 'namespaceURISpecified']
+ [optional uint 32 'serverIndex' 'serverIndexSpecified']
+ ]
+ ['NodeIdType.nodeIdTypeNumeric' ExpandedNodeIdNumeric
+ [simple bit 'serverIndexSpecified']
+ [simple bit 'namespaceURISpecified']
+ [simple NumericNodeId 'id']
+ [optional PascalString 'namespaceURI' 'namespaceURISpecified']
+ [optional uint 32 'serverIndex' 'serverIndexSpecified']
+ ]
+ ['NodeIdType.nodeIdTypeString' ExpandedNodeIdString
+ [simple bit 'serverIndexSpecified']
+ [simple bit 'namespaceURISpecified']
+ [reserved uint 6 '0x00']
+ [simple StringNodeId 'id']
+ [optional PascalString 'namespaceURI' 'namespaceURISpecified']
+ [optional uint 32 'serverIndex' 'serverIndexSpecified']
+ ]
+ ['NodeIdType.nodeIdTypeGuid' ExpandedNodeIdGuid
+ [simple bit 'serverIndexSpecified']
+ [simple bit 'namespaceURISpecified']
+ [simple GuidNodeId 'id']
+ [optional PascalString 'namespaceURI' 'namespaceURISpecified']
+ [optional uint 32 'serverIndex' 'serverIndexSpecified']
+ ]
+ ['NodeIdType.nodeIdTypeByteString' ExpandedNodeIdByteString
+ [simple bit 'serverIndexSpecified']
+ [simple bit 'namespaceURISpecified']
+ [simple ByteStringNodeId 'id']
+ [optional PascalString 'namespaceURI' 'namespaceURISpecified']
+ [optional uint 32 'serverIndex' 'serverIndexSpecified']
+ ]
+ ]
+]
+
+[type 'ExtensionObject'
+ [simple ExpandedNodeId 'nodeId']
+ [simple uint 8 'encodingMask']
+]
+
+[type 'PascalString'
+ [simple int 32 'stringLength']
+ [simple string 'stringLength == -1 ? 0 : stringLength * 8' 'stringValue']
+]
+
+[type 'LocalizedText'
+ [simple uint 6 'reserved1']
+ [simple bit 'localeSpecified']
+ [simple bit 'textSpecified']
+ [optional PascalString 'Locale' 'localeSpecified']
+ [optional PascalString 'Text' 'textSpecified']
+]
+
+[type 'QualifiedName'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='QualifiedName']"/>
+]
+
+[type 'ApplicationDescription'
+ [simple PascalString 'applicationUri']
+ [simple PascalString 'productUri']
+ [simple LocalizedText 'applicationName']
+ [simple ApplicationType 'applicationType']
+ [simple PascalString 'gatewayServerUri']
+ [simple PascalString 'discoveryProfileUri']
+ [simple int 32 'noOfDiscoveryUrls']
+ [optional PascalString 'discoveryUrls' 'noOfDiscoveryUrls > 0']
+]
+
+[type 'EndpointDescription'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='EndpointDescription']"/>
+]
+
+[type 'SignedSoftwareCertificate'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='SignedSoftwareCertificate']"/>
+]
+
+
+[type 'SignatureData'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='SignatureData']"/>
+]
+
+
+[enum int 32 'ApplicationType'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:EnumeratedType[@Name='ApplicationType']"/>
+]
+
+[type 'UserTokenPolicy'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='UserTokenPolicy']"/>
+]
+
+[enum int 32 'UserTokenType'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:EnumeratedType[@Name='UserTokenType']"/>
+]
+
+[enum int 32 'TimestampsToReturn'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:EnumeratedType[@Name='TimestampsToReturn']"/>
+]
+
+[type 'ReadValueId'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='ReadValueId']"/>
+]
+
+[type 'WriteValue'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name='WriteValue']"/>
+]
+
+
+
+ </xsl:template>
+
+ <xsl:template match="node:UAVariable">
+ <xsl:variable name="browseName">
+ <xsl:value-of select='@BrowseName'/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when
test="/opc:TypeDictionary/opc:StructuredType[@Name=$browseName]">
+ <xsl:choose>
+ <xsl:when test="not(@BrowseName='Vector') and
not(substring(@BrowseName,1,1) = '<') and
not(number(substring(@BrowseName,1,1)))">
+ [type '<xsl:value-of select='@BrowseName'/>'
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name=$browseName]"/>
+ ]
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="node:UADataType[not(Definition)]">
+ <xsl:variable name="browseName">
+ <xsl:value-of select='@BrowseName'/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when
test="/opc:TypeDictionary/opc:StructuredType[@Name=$browseName]">
+ <xsl:choose>
+ <xsl:when test="not(Definition) and not(@BrowseName =
'Duration') and not(number(substring(@BrowseName,1,1))) and not(@IsAbstract)
and number(substring(@NodeId,3)) > 29">
+ ['<xsl:value-of select="number(substring(@NodeId,3)) +
2"/><xsl:text>' </xsl:text><xsl:value-of select='@BrowseName'/><xsl:text>
+ </xsl:text>
+ <xsl:apply-templates
select="/opc:TypeDictionary/opc:StructuredType[@Name=$browseName]"/>
+ ]
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
</xsl:template>
<xsl:template match="opc:EnumeratedType">
- [enum int 32 '<xsl:value-of select="@Name"/>'
<xsl:apply-templates select="opc:Documentation"/>
<xsl:apply-templates select="opc:EnumeratedValue"/>
- ]
</xsl:template>
<xsl:template match="opc:Documentation">
@@ -96,13 +593,8 @@
<xsl:with-param name="switchValue" select="@SwitchValue"/>
</xsl:call-template>
</xsl:variable>
- <xsl:choose>
- <xsl:when test="*[@SwitchField]">[discriminatedType '<xsl:value-of
select="@Name"/>'</xsl:when>
- <xsl:when test="not(*[@SwitchField])">[type '<xsl:value-of
select="@Name"/>'</xsl:when>
- </xsl:choose>
- <xsl:apply-templates select="opc:Documentation"/>
- <xsl:apply-templates select="opc:Field"/>
- ]
+ <xsl:apply-templates select="opc:Documentation"/>
+ <xsl:apply-templates select="opc:Field"/>
</xsl:template>
<xsl:template match="opc:Field">
@@ -130,13 +622,8 @@
</xsl:variable>
<xsl:choose>
- <xsl:when test="@LengthField and @TypeName = 'opc:String'">[array
<xsl:value-of select="$dataType"/> '-1' '<xsl:value-of
select="$lowerCaseName"/>' count '<xsl:value-of
select="$lowerCaseLengthField"/>']
- </xsl:when>
<xsl:when test="@LengthField">[array <xsl:value-of
select="$dataType"/> '<xsl:value-of select="$lowerCaseName"/>' count
'<xsl:value-of select="$lowerCaseLengthField"/>']
</xsl:when>
- <xsl:when test="@TypeName = 'opc:String'">[simple int 32
'<xsl:value-of select="$lowerCaseName"/>Size']
- [simple <xsl:value-of select="$dataType"/> '<xsl:value-of
select="$lowerCaseName"/>Size' '<xsl:value-of select="@Name"/>']
- </xsl:when>
<xsl:otherwise>[<xsl:value-of select="$mspecType"/><xsl:text>
</xsl:text><xsl:value-of select="$dataType"/> '<xsl:value-of
select="$lowerCaseName"/>']
</xsl:otherwise>
</xsl:choose>
@@ -181,12 +668,12 @@
<xsl:when test="$datatype = 'opc:UInt64'">uint 64</xsl:when>
<xsl:when test="$datatype = 'opc:Float'">float 8.23</xsl:when>
<xsl:when test="$datatype = 'opc:Double'">float 11.52</xsl:when>
- <xsl:when test="$datatype = 'opc:Char'">string '-1'</xsl:when>
- <xsl:when test="$datatype = 'opc:CharArray'">string '-1'</xsl:when>
+ <xsl:when test="$datatype = 'opc:Char'">string '1'</xsl:when>
+ <xsl:when test="$datatype =
'opc:CharArray'">PascalString</xsl:when>
<xsl:when test="$datatype = 'opc:Guid'">string '-1'</xsl:when>
- <xsl:when test="$datatype = 'opc:ByteString'">string
'-1'</xsl:when>
- <xsl:when test="$datatype = 'opc:DateTime'">string '-1'</xsl:when>
- <xsl:when test="$datatype = 'opc:String'">string</xsl:when>
+ <xsl:when test="$datatype =
'opc:ByteString'">PascalString</xsl:when>
+ <xsl:when test="$datatype = 'opc:DateTime'">int 64</xsl:when>
+ <xsl:when test="$datatype = 'opc:String'">PascalString</xsl:when>
<xsl:otherwise><xsl:value-of
select="substring-after($datatype,':')"/></xsl:otherwise>
</xsl:choose>
</xsl:template>