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
commit 773a691c89ac2b97682b5b631e13cf36afad3972 Author: hutcheb <[email protected]> AuthorDate: Wed Apr 14 04:21:50 2021 -0400 Looking at NodeId disriminator issue --- build-utils/language-java/pom.xml | 1 + .../language/java/JavaLanguageTemplateHelper.java | 22 + .../templates/java/pojo-template.java.ftlh | 25 +- .../definitions/DefaultComplexTypeDefinition.java | 6 + plc4j/drivers/opcua/pom.xml | 6 +- .../opcua/connection/OpcuaTcpPlcConnection.java | 919 --------------------- protocols/opcua/pom.xml | 10 +- .../src/main/resources/protocols/opcua/opcua.mspec | 10 - protocols/opcua/src/main/xslt/opc-types.xsl | 67 +- 9 files changed, 79 insertions(+), 987 deletions(-) diff --git a/build-utils/language-java/pom.xml b/build-utils/language-java/pom.xml index 85438f6..6735743 100644 --- a/build-utils/language-java/pom.xml +++ b/build-utils/language-java/pom.xml @@ -108,6 +108,7 @@ <artifactId>maven-invoker-plugin</artifactId> <version>3.2.2</version> <configuration> + <skipInvocation>${skipTests}</skipInvocation> <debug>true</debug> <projectsDirectory>src/test/resources</projectsDirectory> <cloneProjectsTo>${project.build.directory}/integration-tests</cloneProjectsTo> 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 19bbedd..de22ad5 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 @@ -503,23 +503,33 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe } public String toSerializationExpression(TypedField field, Term term, Argument[] serializerArgments) { + System.out.println(field); + System.out.println(term); return toExpression(field, term, term1 -> toVariableSerializationExpression(field, term1, serializerArgments)); } private String toExpression(TypedField field, Term term, Function<Term, String> variableExpressionGenerator) { + System.out.println(field); + System.out.println(term); + if (term == null) { return ""; } if (term instanceof Literal) { if (term instanceof NullLiteral) { + System.out.println("Blah10"); return "null"; } else if (term instanceof BooleanLiteral) { + System.out.println("Blah11"); return Boolean.toString(((BooleanLiteral) term).getValue()); } else if (term instanceof NumericLiteral) { + System.out.println("Blah12"); return ((NumericLiteral) term).getNumber().toString(); } else if (term instanceof StringLiteral) { + System.out.println("Blah13"); return "\"" + ((StringLiteral) term).getValue() + "\""; } else if (term instanceof VariableLiteral) { + System.out.println("Blah14"); VariableLiteral variableLiteral = (VariableLiteral) term; // If this literal references an Enum type, then we have to output it differently. if (getTypeDefinitions().get(variableLiteral.getName()) instanceof EnumTypeDefinition) { @@ -533,6 +543,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe throw new RuntimeException("Unsupported Literal type " + term.getClass().getName()); } } else if (term instanceof UnaryTerm) { + System.out.println("Blah15"); UnaryTerm ut = (UnaryTerm) term; Term a = ut.getA(); switch (ut.getOperation()) { @@ -546,6 +557,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe throw new RuntimeException("Unsupported unary operation type " + ut.getOperation()); } } else if (term instanceof BinaryTerm) { + System.out.println("Blah16"); BinaryTerm bt = (BinaryTerm) term; Term a = bt.getA(); Term b = bt.getB(); @@ -557,6 +569,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe return "(" + toExpression(field, a, variableExpressionGenerator) + ") " + operation + " (" + toExpression(field, b, variableExpressionGenerator) + ")"; } } else if (term instanceof TernaryTerm) { + System.out.println("Blah17"); TernaryTerm tt = (TernaryTerm) term; if ("if".equals(tt.getOperation())) { Term a = tt.getA(); @@ -574,6 +587,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe private String toVariableParseExpression(TypedField field, Term term, Argument[] parserArguments) { VariableLiteral vl = (VariableLiteral) term; // CAST expressions are special as we need to add a ".class" to the second parameter in Java. + System.out.println("Blah1"); if ("CAST".equals(vl.getName())) { StringBuilder sb = new StringBuilder(vl.getName()); if ((vl.getArgs() == null) || (vl.getArgs().size() != 2)) { @@ -642,10 +656,12 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe } // If we are accessing implicit fields, we need to rely on a local variable instead. else if (isVariableLiteralImplicitField(vl)) { + System.out.println("Blah2"); return vl.getName(); } // All uppercase names are not fields, but utility methods. else if (vl.getName().equals(vl.getName().toUpperCase())) { + System.out.println("Blah3"); StringBuilder sb = new StringBuilder(vl.getName()); if (vl.getArgs() != null) { sb.append("("); @@ -662,12 +678,18 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe if (vl.getIndex() != VariableLiteral.NO_INDEX) { sb.append("[").append(vl.getIndex()).append("]"); } + System.out.println("Blah4"); return sb.toString() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : ""); } + System.out.println("Blah5"); return vl.getName() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : ""); } private String toVariableSerializationExpression(TypedField field, Term term, Argument[] serialzerArguments) { + System.out.println(field); + System.out.println(term); + System.out.println(serialzerArguments); + VariableLiteral vl = (VariableLiteral) term; if ("STATIC_CALL".equals(vl.getName())) { StringBuilder sb = new StringBuilder(); diff --git a/build-utils/language-java/src/main/resources/templates/java/pojo-template.java.ftlh b/build-utils/language-java/src/main/resources/templates/java/pojo-template.java.ftlh index dad0cf8..6e0aff3 100644 --- a/build-utils/language-java/src/main/resources/templates/java/pojo-template.java.ftlh +++ b/build-utils/language-java/src/main/resources/templates/java/pojo-template.java.ftlh @@ -23,7 +23,7 @@ <#-- @ftlvariable name="protocolName" type="java.lang.String" --> <#-- @ftlvariable name="outputFlavor" type="java.lang.String" --> <#-- @ftlvariable name="helper" type="org.apache.plc4x.language.java.JavaLanguageTemplateHelper" --> -<#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition" --> +<#-- @ftlvariable name="type" type="org.apache.plc4x.plugins.codegenerator.language.mspec.model.definitions.DefaultComplexTypeDefinition" --> <#-- Declare the name and type of variables declared locally inside the template --> <#-- @ftlvariable name="arrayField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ArrayField" --> <#-- @ftlvariable name="checksumField" type="org.apache.plc4x.plugins.codegenerator.types.fields.ChecksumField" --> @@ -151,20 +151,24 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ </#list> } +<#list type.getAbstractFields() as field> + public abstract ${helper.getLanguageTypeNameForField(field)}<#if field.loopType??>[]</#if> get${field.name?cap_first}(); + +</#list> + <#list type.propertyFields as field> - <#if helper.isAbstractField(field)> - public ${helper.getLanguageTypeNameForField(field)}<#if field.loopType??>[]</#if> abstract get${field.name?cap_first}(); - <#else> public ${helper.getLanguageTypeNameForField(field)}<#if field.loopType??>[]</#if> get${field.name?cap_first}() { return ${field.name}; } - </#if> </#list> + <#list type.virtualFields as field> + <#if helper.isNonDiscriminatorField(field.name)> public ${helper.getLanguageTypeNameForField(field)}<#if field.loopType??>[]</#if> get${field.name?cap_first}() { return (${helper.getLanguageTypeNameForField(field)}) (${helper.toParseExpression(field, field.valueExpression, type.parserArguments)}); } + </#if> </#list> @Override @@ -216,9 +220,9 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ <#if helper.isSimpleTypeReference(discriminatorField.type)> <#assign simpleTypeReference = discriminatorField.type> <#if helper.getLanguageTypeNameForTypeReference(discriminatorField.type) = "String"> - lengthInBits += ${toSerializationExpression(discriminatorField, simpleTypeReference.getLengthExpression(), type.parserArguments)}; + lengthInBits += ${helper.toSerializationExpression(discriminatorField, simpleTypeReference.getLengthExpression(), type.parserArguments)}; <#else> - lengthInBits += ${simpleTypeReference.sizeInBits}; + lengthInBits += ${simpleTypeReference.sizeInBits}; </#if> <#elseif helper.isEnumField(field)> lengthInBits += ${helper.getEnumBaseTypeReference(discriminatorField.type).sizeInBits}; @@ -258,12 +262,11 @@ public<#if helper.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${ // Optional Field (${optionalField.name}) if(${optionalField.name} != null) { <#if helper.isSimpleTypeReference(optionalField.type)> + <#assign simpleTypeReference = optionalField.type> <#if helper.getLanguageTypeNameForTypeReference(optionalField.type) = "String"> - <#assign simpleTypeReference = optionalField.type> - lengthInBits += ${simpleTypeReference.getLength()}; + lengthInBits += ${helper.toSerializationExpression(discriminatorField, simpleTypeReference.getLengthExpression(), type.parserArguments)}; <#else> - <#assign simpleTypeReference = optionalField.type> - lengthInBits += ${simpleTypeReference.sizeInBits}; + lengthInBits += ${simpleTypeReference.sizeInBits}; </#if> <#elseif helper.isEnumField(field)> lengthInBits += ${helper.getEnumBaseTypeReference(optionalField.type).sizeInBits}; diff --git a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java index 39d87f4..7ab0431 100644 --- a/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java +++ b/build-utils/protocol-base-mspec/src/main/java/org/apache/plc4x/plugins/codegenerator/language/mspec/model/definitions/DefaultComplexTypeDefinition.java @@ -22,6 +22,7 @@ package org.apache.plc4x.plugins.codegenerator.language.mspec.model.definitions; import org.apache.plc4x.plugins.codegenerator.types.definitions.Argument; import org.apache.plc4x.plugins.codegenerator.types.definitions.ComplexTypeDefinition; import org.apache.plc4x.plugins.codegenerator.types.fields.*; +import org.graalvm.compiler.core.common.type.ArithmeticOpTable; import java.util.Collections; import java.util.LinkedList; @@ -65,6 +66,11 @@ public class DefaultComplexTypeDefinition extends DefaultTypeDefinition implemen .collect(Collectors.toList()); } + public List<AbstractField> getAbstractFields() { + return fields.stream().filter(field -> field instanceof AbstractField).map( + field -> (AbstractField) field).collect(Collectors.toList()); + } + @Override public List<VirtualField> getVirtualFields() { return fields.stream().filter(field -> (field instanceof VirtualField)).map(field -> (VirtualField) field) diff --git a/plc4j/drivers/opcua/pom.xml b/plc4j/drivers/opcua/pom.xml index 897ff1b..d23eab6 100644 --- a/plc4j/drivers/opcua/pom.xml +++ b/plc4j/drivers/opcua/pom.xml @@ -124,17 +124,17 @@ <dependency> <groupId>org.apache.plc4x</groupId> <artifactId>plc4j-transport-tcp</artifactId> - <version>0.8.0-SNAPSHOT</version> + <version>0.9.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.apache.plc4x</groupId> <artifactId>plc4j-transport-serial</artifactId> - <version>0.8.0-SNAPSHOT</version> + <version>0.9.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.apache.plc4x</groupId> <artifactId>plc4j-transport-raw-socket</artifactId> - <version>0.8.0-SNAPSHOT</version> + <version>0.9.0-SNAPSHOT</version> </dependency> diff --git a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java deleted file mode 100644 index 458d5f1..0000000 --- a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/connection/OpcuaTcpPlcConnection.java +++ /dev/null @@ -1,919 +0,0 @@ -/* - 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.connection; - -import org.apache.plc4x.java.api.exceptions.PlcConnectionException; -import org.apache.plc4x.java.api.messages.*; -import org.apache.plc4x.java.api.model.PlcConsumerRegistration; -import org.apache.plc4x.java.api.model.PlcField; -import org.apache.plc4x.java.api.model.PlcSubscriptionField; -import org.apache.plc4x.java.api.model.PlcSubscriptionHandle; -import org.apache.plc4x.java.api.types.PlcResponseCode; -import org.apache.plc4x.java.api.value.*; -import org.apache.plc4x.java.opcua.protocol.OpcuaField; -import org.apache.plc4x.java.opcua.protocol.OpcuaSubsriptionHandle; -import org.apache.plc4x.java.spi.messages.*; -import org.apache.plc4x.java.spi.messages.utils.ResponseItem; -import org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration; -import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField; -import org.apache.plc4x.java.spi.values.*; -import org.eclipse.milo.opcua.sdk.client.OpcUaClient; -import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig; -import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider; -import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider; -import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem; -import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription; -import org.eclipse.milo.opcua.stack.client.DiscoveryClient; -import org.eclipse.milo.opcua.stack.core.AttributeId; -import org.eclipse.milo.opcua.stack.core.Identifiers; -import org.eclipse.milo.opcua.stack.core.UaException; -import org.eclipse.milo.opcua.stack.core.StatusCodes; -import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy; -import org.eclipse.milo.opcua.stack.core.types.builtin.*; -import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.*; -import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode; -import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn; -import org.eclipse.milo.opcua.stack.core.types.structured.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.math.BigInteger; -import java.math.BigDecimal; -import java.util.stream.Collectors; -import java.net.InetAddress; -import java.time.Duration; -import java.time.LocalDateTime; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Predicate; - -import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint; -import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.ulong; - -/** - * Corresponding implementaion for a TCP-based connection for an OPC UA server. - * TODO: At the moment are just connections without any security mechanism possible - * <p> - */ -public class OpcuaTcpPlcConnection extends BaseOpcuaPlcConnection { - - private static final int OPCUA_DEFAULT_TCP_PORT = 4840; - - private static final Logger logger = LoggerFactory.getLogger(OpcuaTcpPlcConnection.class); - private final AtomicLong clientHandles = new AtomicLong(1L); - private InetAddress address; - private int requestTimeout = 5000; - private int port; - private String params; - private OpcUaClient client; - private boolean isConnected = false; - - private OpcuaTcpPlcConnection(InetAddress address, String params, int requestTimeout) { - this(address, OPCUA_DEFAULT_TCP_PORT, params, requestTimeout); - logger.info("Configured OpcuaTcpPlcConnection with: host-name {}", address.getHostAddress()); - } - - private OpcuaTcpPlcConnection(InetAddress address, int port, String params, int requestTimeout) { - this(params); - logger.info("Configured OpcuaTcpPlcConnection with: host-name {}", address.getHostAddress()); - this.address = address; - this.port = port; - this.params = params; - this.requestTimeout = requestTimeout; - } - - private OpcuaTcpPlcConnection(String params) { - super(getOptionString(params)); - } - - public static OpcuaTcpPlcConnection of(InetAddress address, String params, int requestTimeout) { - return new OpcuaTcpPlcConnection(address, params, requestTimeout); - } - - public static OpcuaTcpPlcConnection of(InetAddress address, int port, String params, int requestTimeout) { - return new OpcuaTcpPlcConnection(address, port, params, requestTimeout); - } - - public static PlcValue encodePlcValue(DataValue value) { - ExpandedNodeId typeNode = value.getValue().getDataType().get(); - Object objValue = value.getValue().getValue(); - - if (objValue.getClass().isArray()) { - Object[] objArray = (Object[]) objValue; - if (objArray[0] instanceof Boolean) { - Boolean[] obj = (Boolean[]) objValue; - List<PlcValue> plcValue; - { - int itemCount = (int) obj.length; - plcValue = new LinkedList<>(); - - for(int curItem = 0; curItem < itemCount; curItem++) { - plcValue.add(new PlcBOOL((Boolean) obj[curItem])); - } - } - return new PlcList(plcValue); - } else if (objArray[0] instanceof Integer) { - Integer[] obj = (Integer[]) objValue; - List<PlcValue> plcValue; - { - int itemCount = (int) obj.length; - plcValue = new LinkedList<>(); - - for(int curItem = 0; curItem < itemCount; curItem++) { - plcValue.add(new PlcDINT((Integer) obj[curItem])); - } - } - return new PlcList(plcValue); - } else if (objArray[0] instanceof Short) { - Short[] obj = (Short[]) objValue; - List<PlcValue> plcValue; - { - int itemCount = (int) obj.length; - plcValue = new LinkedList<>(); - - for(int curItem = 0; curItem < itemCount; curItem++) { - plcValue.add(new PlcINT((Short) obj[curItem])); - } - } - return new PlcList(plcValue); - } else if (objArray[0] instanceof Byte) { - Byte[] obj = (Byte[]) objValue; - List<PlcValue> plcValue; - { - int itemCount = (int) obj.length; - plcValue = new LinkedList<>(); - - for(int curItem = 0; curItem < itemCount; curItem++) { - plcValue.add(new PlcSINT((Byte) obj[curItem])); - } - } - return new PlcList(plcValue); - } else if (objArray[0] instanceof Long) { - Long[] obj = (Long[]) objValue; - List<PlcValue> plcValue; - { - int itemCount = (int) obj.length; - plcValue = new LinkedList<>(); - - for(int curItem = 0; curItem < itemCount; curItem++) { - plcValue.add(new PlcLINT((Long) obj[curItem])); - } - } - return new PlcList(plcValue); - } else if (objArray[0] instanceof Float) { - Float[] obj = (Float[]) objValue; - List<PlcValue> plcValue; - { - int itemCount = (int) obj.length; - plcValue = new LinkedList<>(); - - for(int curItem = 0; curItem < itemCount; curItem++) { - plcValue.add(new PlcREAL((Float) obj[curItem])); - } - } - return new PlcList(plcValue); - } else if (objArray[0] instanceof Double) { - Double[] obj = (Double[]) objValue; - List<PlcValue> plcValue; - { - int itemCount = (int) obj.length; - plcValue = new LinkedList<>(); - - for(int curItem = 0; curItem < itemCount; curItem++) { - plcValue.add(new PlcLREAL((Double) obj[curItem])); - } - } - return new PlcList(plcValue); - } else if (objArray[0] instanceof String) { - String[] obj = (String[]) objValue; - List<PlcValue> plcValue; - { - int itemCount = (int) obj.length; - plcValue = new LinkedList<>(); - - for(int curItem = 0; curItem < itemCount; curItem++) { - plcValue.add(new PlcSTRING((String) obj[curItem])); - } - } - return new PlcList(plcValue); - } else { - logger.warn("Node type for " + objArray[0].getClass() + " is not supported"); - return null; - } - - } else { - if (typeNode.equals(Identifiers.Boolean)) { - return new PlcBOOL((Boolean) objValue); - } else if (typeNode.equals(Identifiers.Integer)) { - return new PlcDINT((Integer) objValue); - } else if (typeNode.equals(Identifiers.Int16)) { - return new PlcINT((Short) objValue); - } else if (typeNode.equals(Identifiers.Int32)) { - return new PlcDINT((Integer) objValue); - } else if (typeNode.equals(Identifiers.Int64)) { - return new PlcLINT((Long) objValue); - } else if (typeNode.equals(Identifiers.UInteger)) { - return new PlcLINT((Long) objValue); - } else if (typeNode.equals(Identifiers.UInt16)) { - return new PlcUINT(((UShort) objValue).intValue()); - } else if (typeNode.equals(Identifiers.UInt32)) { - return new PlcUDINT(((UInteger) objValue).longValue()); - } else if (typeNode.equals(Identifiers.UInt64)) { - return new PlcULINT(new BigInteger(objValue.toString())); - } else if (typeNode.equals(Identifiers.Byte)) { - return new PlcINT(Short.valueOf(objValue.toString())); - } else if (typeNode.equals(Identifiers.Float)) { - return new PlcREAL((Float) objValue); - } else if (typeNode.equals(Identifiers.Double)) { - return new PlcLREAL((Double) objValue); - } else if (typeNode.equals(Identifiers.SByte)) { - return new PlcSINT((Byte) objValue); - } else { - return new PlcSTRING(objValue.toString()); - } - } - - } - - public InetAddress getRemoteAddress() { - return address; - } - - @Override - public void connect() throws PlcConnectionException { - List<EndpointDescription> endpoints = null; - EndpointDescription endpoint = null; - - try { - endpoints = DiscoveryClient.getEndpoints(getEndpointUrl(address, port, getSubPathOfParams(params))).get(); - //TODO Exception should be handeled better when the Discovery-API of Milo is stable - } catch (Exception ex) { - logger.info("Failed to discover Endpoint with enabled discovery. If the endpoint does not allow a correct discovery disable this option with the nDiscovery=true option. Failed Endpoint: {}", getEndpointUrl(address, port, params)); - - // try the explicit discovery endpoint as well - String discoveryUrl = getEndpointUrl(address, port, getSubPathOfParams(params)); - - if (!discoveryUrl.endsWith("/")) { - discoveryUrl += "/"; - } - discoveryUrl += "discovery"; - - logger.info("Trying explicit discovery URL: {}", discoveryUrl); - try { - endpoints = DiscoveryClient.getEndpoints(discoveryUrl).get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new PlcConnectionException("Unable to discover URL:" + discoveryUrl); - } catch (ExecutionException e) { - throw new PlcConnectionException("Unable to discover URL:" + discoveryUrl); - } - - } - endpoint = endpoints.stream() - .filter(e -> e.getSecurityPolicyUri().equals(getSecurityPolicy().getUri())) - .filter(endpointFilter()) - .findFirst() - .orElseThrow(() -> new PlcConnectionException("No desired endpoints from")); - - if (this.skipDiscovery) { - //ApplicationDescription applicationDescription = new ApplicationDescription(); - //endpoint = new EndpointDescription(address.getHostAddress(),applicationDescription , null, MessageSecurityMode.None, SecurityPolicy.None.getUri(), null , TransportProfile.TCP_UASC_UABINARY.getUri(), UByte.valueOf(0));// TODO hier machen wenn fertig - ApplicationDescription currentAD = endpoint.getServer(); - ApplicationDescription withoutDiscoveryAD = new ApplicationDescription( - currentAD.getApplicationUri(), - currentAD.getProductUri(), - currentAD.getApplicationName(), - currentAD.getApplicationType(), - currentAD.getGatewayServerUri(), - currentAD.getDiscoveryProfileUri(), - new String[0]); - //try to replace the overhanded address - //any error will result in the overhanded address of the client - String newEndpointUrl = endpoint.getEndpointUrl(), prefix = "", suffix = ""; - String splitterPrefix = "://"; - String splitterSuffix = ":"; - String[] prefixSplit = newEndpointUrl.split(splitterPrefix); - if (prefixSplit.length > 1) { - String[] suffixSplit = prefixSplit[1].split(splitterSuffix); - //reconstruct the uri - newEndpointUrl = ""; - newEndpointUrl += prefixSplit[0] + splitterPrefix + address.getHostAddress(); - for (int suffixCounter = 1; suffixCounter < suffixSplit.length; suffixCounter++) { - newEndpointUrl += splitterSuffix + suffixSplit[suffixCounter]; - } - // attach surounding prefix match - for (int prefixCounter = 2; prefixCounter < prefixSplit.length; prefixCounter++) { - newEndpointUrl += splitterPrefix + prefixSplit[prefixCounter]; - } - } - - EndpointDescription noDiscoverEndpoint = new EndpointDescription( - newEndpointUrl, - withoutDiscoveryAD, - endpoint.getServerCertificate(), - endpoint.getSecurityMode(), - endpoint.getSecurityPolicyUri(), - endpoint.getUserIdentityTokens(), - endpoint.getTransportProfileUri(), - endpoint.getSecurityLevel()); - endpoint = noDiscoverEndpoint; - } - - - OpcUaClientConfig config = OpcUaClientConfig.builder() - .setApplicationName(LocalizedText.english("eclipse milo opc-ua client of the apache PLC4X:PLC4J project")) - .setApplicationUri("urn:eclipse:milo:plc4x:client") - .setEndpoint(endpoint) - .setIdentityProvider(getIdentityProvider()) - .setRequestTimeout(UInteger.valueOf(requestTimeout)) - .build(); - - try { - this.client = OpcUaClient.create(config); - this.client.connect().get(); - isConnected = true; - } catch (UaException e) { - isConnected = false; - String message = (config == null) ? "NULL" : config.toString(); - throw new PlcConnectionException("The given input values are a not valid OPC UA connection configuration [CONFIG]: " + message); - } catch (InterruptedException e) { - isConnected = false; - Thread.currentThread().interrupt(); - throw new PlcConnectionException("Error while creation of the connection because of : " + e.getMessage()); - } catch (ExecutionException e) { - isConnected = false; - throw new PlcConnectionException("Error while creation of the connection because of : " + e.getMessage()); - } - } - - @Override - public boolean isConnected() { - return client != null && isConnected; - } - - @Override - public void close() throws Exception { - if (client != null) { - client.disconnect().get(); - isConnected = false; - } - } - - @Override - public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionRequest subscriptionRequest) { - CompletableFuture<PlcSubscriptionResponse> future = CompletableFuture.supplyAsync(() -> { - Map<String, ResponseItem<PlcSubscriptionHandle>> responseItems = new HashMap<>(); - for (String fieldName : subscriptionRequest.getFieldNames()) { - final DefaultPlcSubscriptionField subscriptionField = (DefaultPlcSubscriptionField) subscriptionRequest.getField(fieldName); - final OpcuaField field = (OpcuaField) Objects.requireNonNull(subscriptionField.getPlcField()); - long cycleTime = subscriptionField.getDuration().orElse(Duration.ofSeconds(1)).toMillis(); - NodeId idNode = generateNodeId(field); - ReadValueId readValueId = new ReadValueId( - idNode, - AttributeId.Value.uid(), null, QualifiedName.NULL_VALUE); - UInteger clientHandle = uint(clientHandles.getAndIncrement()); - - MonitoringMode monitoringMode; - switch (subscriptionField.getPlcSubscriptionType()) { - case CYCLIC: - monitoringMode = MonitoringMode.Sampling; - break; - case CHANGE_OF_STATE: - monitoringMode = MonitoringMode.Reporting; - cycleTime = subscriptionField.getDuration().orElse(Duration.ofSeconds(0)).toMillis(); - break; - case EVENT: - monitoringMode = MonitoringMode.Reporting; - break; - default: - monitoringMode = MonitoringMode.Reporting; - } - - MonitoringParameters parameters = new MonitoringParameters( - clientHandle, - (double) cycleTime, // sampling interval - null, // filter, null means use default - uint(1), // queue size - true // discard oldest - ); - - PlcSubscriptionHandle subHandle = null; - PlcResponseCode responseCode = PlcResponseCode.ACCESS_DENIED; - try { - UaSubscription subscription = client.getSubscriptionManager().createSubscription(cycleTime).get(); - - MonitoredItemCreateRequest request = new MonitoredItemCreateRequest( - readValueId, monitoringMode, parameters); - List<MonitoredItemCreateRequest> requestList = new LinkedList<>(); - requestList.add(request); - OpcuaSubsriptionHandle subsriptionHandle = new OpcuaSubsriptionHandle(fieldName, clientHandle); - BiConsumer<UaMonitoredItem, Integer> onItemCreated = - (item, id) -> item.setValueConsumer(subsriptionHandle::onSubscriptionValue); - - List<UaMonitoredItem> items = subscription.createMonitoredItems( - TimestampsToReturn.Both, - requestList, - onItemCreated - ).get(); - - subHandle = subsriptionHandle; - responseCode = PlcResponseCode.OK; - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - logger.warn("Unable to subscribe Elements because of: {}", e.getMessage()); - } catch (ExecutionException e) { - logger.warn("Unable to subscribe Elements because of: {}", e.getMessage()); - } - - responseItems.put(fieldName, new ResponseItem(responseCode, subHandle)); - } - return new DefaultPlcSubscriptionResponse(subscriptionRequest, responseItems); - }); - - return future; - } - - @Override - public CompletableFuture<PlcUnsubscriptionResponse> unsubscribe(PlcUnsubscriptionRequest unsubscriptionRequest) { - unsubscriptionRequest.getSubscriptionHandles().forEach(o -> { - OpcuaSubsriptionHandle opcSubHandle = (OpcuaSubsriptionHandle) o; - try { - client.getSubscriptionManager().deleteSubscription(opcSubHandle.getClientHandle()).get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - logger.warn("Unable to unsubscribe Elements because of: {}", e.getMessage()); - } catch (ExecutionException e) { - logger.warn("Unable to unsubscribe Elements because of: {}", e.getMessage()); - } - }); - - return null; - } - - @Override - public PlcConsumerRegistration register(Consumer<PlcSubscriptionEvent> consumer, Collection<PlcSubscriptionHandle> handles) { - List<PlcConsumerRegistration> registrations = new LinkedList<>(); - // Register the current consumer for each of the given subscription handles - for (PlcSubscriptionHandle subscriptionHandle : handles) { - final PlcConsumerRegistration consumerRegistration = subscriptionHandle.register(consumer); - registrations.add(consumerRegistration); - } - - return new DefaultPlcConsumerRegistration(this, consumer, handles.toArray(new PlcSubscriptionHandle[0])); - } - - @Override - public void unregister(PlcConsumerRegistration registration) { - registration.unregister(); - } - - @Override - public CompletableFuture<PlcReadResponse> read(PlcReadRequest readRequest) { - CompletableFuture<PlcReadResponse> future = CompletableFuture.supplyAsync(() -> { - readRequest.getFields(); - Map<String, ResponseItem<PlcValue>> fields = new HashMap<>(); - List<NodeId> readValueIds = new LinkedList<>(); - List<PlcField> readPLCValues = readRequest.getFields(); - for (PlcField field : readPLCValues) { - NodeId idNode = generateNodeId((OpcuaField) field); - readValueIds.add(idNode); - } - - CompletableFuture<List<DataValue>> dataValueCompletableFuture = client.readValues(0.0, TimestampsToReturn.Both, readValueIds); - List<DataValue> readValues = null; - try { - readValues = dataValueCompletableFuture.get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - logger.warn("Unable to read Elements because of: {}", e.getMessage()); - } catch (ExecutionException e) { - logger.warn("Unable to read Elements because of: {}", e.getMessage()); - } - for (int counter = 0; counter < readValueIds.size(); counter++) { - PlcResponseCode resultCode = PlcResponseCode.OK; - PlcValue stringItem = null; - if (readValues == null || readValues.size() <= counter || - !readValues.get(counter).getStatusCode().equals(StatusCode.GOOD)) { - resultCode = PlcResponseCode.NOT_FOUND; - } else { - stringItem = encodePlcValue(readValues.get(counter)); - - } - ResponseItem<PlcValue> newPair = new ResponseItem<>(resultCode, stringItem); - fields.put((String) readRequest.getFieldNames().toArray()[counter], newPair); - - - } - return new DefaultPlcReadResponse(readRequest, fields); - }); - - return future; - } - - - @Override - public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) { - CompletableFuture<PlcWriteResponse> future; - future = CompletableFuture.supplyAsync(() -> { - List<PlcField> writePLCValues = writeRequest.getFields(); - LinkedList<DataValue> values = new LinkedList<>(); - LinkedList<NodeId> ids = new LinkedList<>(); - LinkedList<String> names = new LinkedList<>(); - Map<String, PlcResponseCode> fieldResponse = new HashMap<>(); - for (String fieldName : writeRequest.getFieldNames()) { - OpcuaField uaField = (OpcuaField) writeRequest.getField(fieldName); - NodeId idNode = generateNodeId(uaField); - Object valueObject = writeRequest.getPlcValue(fieldName).getObject(); - // Added small work around for handling BigIntegers as input type for UInt64 - if (valueObject instanceof BigInteger) valueObject = ulong((BigInteger) valueObject); - Variant var = null; - if (valueObject instanceof ArrayList) { - List<PlcValue> plcValueList = (List<PlcValue>) valueObject; - String dataType = uaField.getPlcDataType(); - if (dataType.equals("NULL")) { - if (plcValueList.get(0).getObject() instanceof Boolean) { - dataType = "BOOL"; - } else if (plcValueList.get(0).getObject() instanceof Byte) { - dataType = "SINT"; - } else if (plcValueList.get(0).getObject() instanceof Short) { - dataType = "INT"; - } else if (plcValueList.get(0).getObject() instanceof Integer) { - dataType = "DINT"; - } else if (plcValueList.get(0).getObject() instanceof Long) { - dataType = "LINT"; - } else if (plcValueList.get(0).getObject() instanceof Float) { - dataType = "REAL"; - } else if (plcValueList.get(0).getObject() instanceof Double) { - dataType = "LREAL"; - } else if (plcValueList.get(0).getObject() instanceof String) { - dataType = "STRING"; - } - } - switch (dataType) { - case "BOOL": - case "BIT": - List<Boolean> booleanList = (plcValueList).stream().map( - x -> ((PlcBOOL) x).getBoolean()).collect(Collectors.toList()); - var = new Variant(booleanList.toArray(new Boolean[booleanList.size()])); - break; - case "BYTE": - case "BITARR8": - List<UByte> byteList = (plcValueList).stream().map( - x -> UByte.valueOf(((PlcBYTE) x).getShort())).collect(Collectors.toList()); - var = new Variant(byteList.toArray(new UByte[byteList.size()])); - break; - case "SINT": - case "INT8": - List<Byte> sintList = (plcValueList).stream().map( - x -> ((PlcSINT) x).getByte()).collect(Collectors.toList()); - var = new Variant(sintList.toArray(new Byte[sintList.size()])); - break; - case "USINT": - case "UINT8": - case "BIT8": - List<UByte> usintList = (plcValueList).stream().map( - x -> UByte.valueOf(((PlcUSINT) x).getShort())).collect(Collectors.toList()); - var = new Variant(usintList.toArray(new UByte[usintList.size()])); - break; - case "INT": - case "INT16": - List<Short> intList = (plcValueList).stream().map( - x -> ((PlcINT) x).getShort()).collect(Collectors.toList()); - var = new Variant(intList.toArray(new Short[intList.size()])); - break; - case "UINT": - case "UINT16": - List<UShort> uintList = (plcValueList).stream().map( - x -> UShort.valueOf(((PlcUINT) x).getInteger())).collect(Collectors.toList()); - var = new Variant(uintList.toArray(new UShort[uintList.size()])); - break; - case "WORD": - case "BITARR16": - List<UShort> wordList = (plcValueList).stream().map( - x -> UShort.valueOf(((PlcWORD) x).getInteger())).collect(Collectors.toList()); - var = new Variant(wordList.toArray(new UShort[wordList.size()])); - break; - case "DINT": - case "INT32": - List<Integer> dintList = (plcValueList).stream().map( - x -> ((PlcDINT) x).getInteger()).collect(Collectors.toList()); - var = new Variant(dintList.toArray(new Integer[dintList.size()])); - break; - case "UDINT": - case "UINT32": - List<UInteger> udintList = (plcValueList).stream().map( - x -> UInteger.valueOf(((PlcUDINT) x).getLong())).collect(Collectors.toList()); - var = new Variant(udintList.toArray(new UInteger[udintList.size()])); - break; - case "DWORD": - case "BITARR32": - List<UInteger> dwordList = (plcValueList).stream().map( - x -> UInteger.valueOf(((PlcDWORD) x).getLong())).collect(Collectors.toList()); - var = new Variant(dwordList.toArray(new UInteger[dwordList.size()])); - break; - case "LINT": - case "INT64": - List<Long> lintList = (plcValueList).stream().map( - x -> ((PlcLINT) x).getLong()).collect(Collectors.toList()); - var = new Variant(lintList.toArray(new Long[lintList.size()])); - break; - case "ULINT": - case "UINT64": - List<ULong> ulintList = (plcValueList).stream().map( - x -> ULong.valueOf(((PlcULINT) x).getBigInteger())).collect(Collectors.toList()); - var = new Variant(ulintList.toArray(new ULong[ulintList.size()])); - break; - case "LWORD": - case "BITARR64": - List<ULong> lwordList = (plcValueList).stream().map( - x -> ULong.valueOf(((PlcLWORD) x).getBigInteger())).collect(Collectors.toList()); - var = new Variant(lwordList.toArray(new ULong[lwordList.size()])); - break; - case "REAL": - case "FLOAT": - List<Float> realList = (plcValueList).stream().map( - x -> ((PlcREAL) x).getFloat()).collect(Collectors.toList()); - var = new Variant(realList.toArray(new Float[realList.size()])); - break; - case "LREAL": - case "DOUBLE": - List<Double> lrealList = (plcValueList).stream().map( - x -> (Double) ((PlcLREAL) x).getDouble()).collect(Collectors.toList()); - var = new Variant(lrealList.toArray(new Double[lrealList.size()])); - break; - case "CHAR": - List<String> charList = (plcValueList).stream().map( - x -> ((PlcCHAR) x).getString()).collect(Collectors.toList()); - var = new Variant(charList.toArray(new String[charList.size()])); - break; - case "WCHAR": - List<String> wcharList = (plcValueList).stream().map( - x -> ((PlcWCHAR) x).getString()).collect(Collectors.toList()); - var = new Variant(wcharList.toArray(new String[wcharList.size()])); - break; - case "STRING": - List<String> stringList = (plcValueList).stream().map( - x -> ((PlcSTRING) x).getString()).collect(Collectors.toList()); - var = new Variant(stringList.toArray(new String[stringList.size()])); - break; - case "WSTRING": - case "STRING16": - List<String> wstringList = (plcValueList).stream().map( - x -> (String) ((PlcSTRING) x).getString()).collect(Collectors.toList()); - var = new Variant(wstringList.toArray(new String[wstringList.size()])); - break; - case "DATE_AND_TIME": - List<LocalDateTime> dateTimeList = (plcValueList).stream().map( - x -> ((PlcDATE_AND_TIME) x).getDateTime()).collect(Collectors.toList()); - var = new Variant(dateTimeList.toArray(new LocalDateTime[dateTimeList.size()])); - break; - default: - logger.warn("Unsupported data type : {}, {}", plcValueList.get(0).getClass(), dataType); - } - } else { - String dataType = uaField.getPlcDataType(); - PlcValue plcValue = (PlcValue) writeRequest.getPlcValue(fieldName); - - if (dataType.equals("NULL")) { - if (plcValue.getObject() instanceof Boolean) { - dataType = "BOOL"; - } else if (plcValue.getObject() instanceof Byte) { - dataType = "SINT"; - } else if (plcValue.getObject() instanceof Short) { - dataType = "INT"; - } else if (plcValue.getObject() instanceof Integer) { - dataType = "DINT"; - } else if (plcValue.getObject() instanceof Long) { - dataType = "LINT"; - } else if (plcValue.getObject() instanceof Float) { - dataType = "REAL"; - } else if (plcValue.getObject() instanceof Double) { - dataType = "LREAL"; - } else if (plcValue.getObject() instanceof String) { - dataType = "STRING"; - } - } - switch (dataType) { - case "BOOL": - case "BIT": - var = new Variant(plcValue.getBoolean()); - break; - case "BYTE": - case "BITARR8": - var = new Variant(UByte.valueOf(plcValue.getShort())); - break; - case "SINT": - case "INT8": - var = new Variant(plcValue.getByte()); - break; - case "USINT": - case "UINT8": - case "BIT8": - var = new Variant(UByte.valueOf(plcValue.getShort())); - break; - case "INT": - case "INT16": - var = new Variant(plcValue.getShort()); - break; - case "UINT": - case "UINT16": - var = new Variant(UShort.valueOf(plcValue.getInteger())); - break; - case "WORD": - case "BITARR16": - var = new Variant(UShort.valueOf(plcValue.getInteger())); - break; - case "DINT": - case "INT32": - var = new Variant(plcValue.getInteger()); - break; - case "UDINT": - case "UINT32": - var = new Variant(UInteger.valueOf(plcValue.getLong())); - break; - case "DWORD": - case "BITARR32": - var = new Variant(UInteger.valueOf(plcValue.getLong())); - break; - case "LINT": - case "INT64": - var = new Variant(plcValue.getLong()); - break; - case "ULINT": - case "UINT64": - var = new Variant(ULong.valueOf(plcValue.getBigInteger())); - break; - case "LWORD": - case "BITARR64": - var = new Variant(ULong.valueOf(plcValue.getBigInteger())); - break; - case "REAL": - case "FLOAT": - var = new Variant(plcValue.getFloat()); - break; - case "LREAL": - case "DOUBLE": - var = new Variant(plcValue.getDouble()); - break; - case "CHAR": - var = new Variant(plcValue.getString()); - break; - case "WCHAR": - var = new Variant(plcValue.getString()); - break; - case "STRING": - var = new Variant(plcValue.getString()); - break; - case "WSTRING": - case "STRING16": - var = new Variant(plcValue.getString()); - break; - case "DATE_AND_TIME": - var = new Variant(plcValue.getDateTime()); - break; - default: - logger.warn("Unsupported data type : {}, {}", plcValue.getClass(), dataType); - } - } - DataValue value = new DataValue(var, StatusCode.GOOD, null, null); - ids.add(idNode); - names.add(fieldName); - values.add(value); - } - CompletableFuture<List<StatusCode>> opcRequest = - client.writeValues(ids, values); - List<StatusCode> statusCodes = null; - try { - statusCodes = opcRequest.get(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - statusCodes = new LinkedList<>(); - for (int counter = 0; counter < ids.size(); counter++) { - ((LinkedList<StatusCode>) statusCodes).push(StatusCode.BAD); - } - } catch (ExecutionException e) { - statusCodes = new LinkedList<>(); - for (int counter = 0; counter < ids.size(); counter++) { - ((LinkedList<StatusCode>) statusCodes).push(StatusCode.BAD); - } - } - - for (int counter = 0; counter < names.size(); counter++) { - final PlcResponseCode resultCode; - if (statusCodes != null && statusCodes.size() > counter) { - Optional<String[]> status = StatusCodes.lookup(statusCodes.get(counter).getValue()); - if (status.isPresent()) { - if (status.get()[0].equals("Good")) { - resultCode = PlcResponseCode.OK; - } else if (status.get()[0].equals("Uncertain")) { - resultCode = PlcResponseCode.NOT_FOUND; - } else if (status.get()[0].equals("Bad")) { - resultCode = PlcResponseCode.INVALID_DATATYPE; - } else if (status.get()[0].equals("Bad_NodeIdUnknown")) { - resultCode = PlcResponseCode.NOT_FOUND; - } else { - resultCode = PlcResponseCode.ACCESS_DENIED; - } - } else { - resultCode = PlcResponseCode.ACCESS_DENIED; - } - } else { - resultCode = PlcResponseCode.ACCESS_DENIED; - } - fieldResponse.put(names.get(counter), resultCode); - } - PlcWriteResponse response = new DefaultPlcWriteResponse(writeRequest, fieldResponse); - return response; - }); - - - return future; - } - - - private NodeId generateNodeId(OpcuaField uaField) { - NodeId idNode = null; - switch (uaField.getIdentifierType()) { - case STRING_IDENTIFIER: - idNode = new NodeId(uaField.getNamespace(), uaField.getIdentifier()); - break; - case NUMBER_IDENTIFIER: - idNode = new NodeId(uaField.getNamespace(), UInteger.valueOf(uaField.getIdentifier())); - break; - case GUID_IDENTIFIER: - idNode = new NodeId(uaField.getNamespace(), UUID.fromString(uaField.getIdentifier())); - break; - case BINARY_IDENTIFIER: - idNode = new NodeId(uaField.getNamespace(), new ByteString(uaField.getIdentifier().getBytes())); - break; - - default: - idNode = new NodeId(uaField.getNamespace(), uaField.getIdentifier()); - } - - return idNode; - } - - private String getEndpointUrl(InetAddress address, Integer port, String params) { - return "opc.tcp://" + address.getHostAddress() + ":" + port + "/" + params; - } - - private Predicate<EndpointDescription> endpointFilter() { - return e -> true; - } - - private SecurityPolicy getSecurityPolicy() { - return SecurityPolicy.None; - } - - private IdentityProvider getIdentityProvider() { - return new AnonymousProvider(); - } - - private static String getSubPathOfParams(String params){ - if(params.contains("=")){ - if(params.contains("?")){ - return params.split("\\?")[0]; - }else{ - return ""; - } - - }else { - return params; - } - } - - private static String getOptionString(String params){ - if(params.contains("=")){ - if(params.contains("?")){ - return params.split("\\?")[1]; - }else{ - return params; - } - - }else { - return ""; - } - } -} diff --git a/protocols/opcua/pom.xml b/protocols/opcua/pom.xml index a055cc5..172539a 100644 --- a/protocols/opcua/pom.xml +++ b/protocols/opcua/pom.xml @@ -46,10 +46,12 @@ <goal>wget</goal> </goals> <configuration> - <url>https://opcfoundation.org/UA/schemas/1.04/Opc.Ua.Types.bsd</url> + <url>https://raw.githubusercontent.com/OPCFoundation/UA-Nodeset/v1.04/Schema/Opc.Ua.Types.bsd</url> <unpack>false</unpack> <outputDirectory>${project.build.directory}/downloads</outputDirectory> <outputFileName>Opc.Ua.Types.bsd</outputFileName> + <skipCache>true</skipCache> + <overwrite>true</overwrite> </configuration> </execution> </executions> @@ -66,7 +68,7 @@ <goal>wget</goal> </goals> <configuration> - <url>https://opcfoundation.org/UA/schemas/1.04/StatusCode.csv</url> + <url>https://raw.githubusercontent.com/OPCFoundation/UA-Nodeset/v1.04/Schema/StatusCode.csv</url> <unpack>false</unpack> <outputDirectory>${project.build.directory}/downloads</outputDirectory> <outputFileName>StatusCode.csv</outputFileName> @@ -85,7 +87,7 @@ <goal>wget</goal> </goals> <configuration> - <url>https://opcfoundation.org/UA/schemas/1.04/Opc.Ua.NodeSet2.Services.xml</url> + <url>https://raw.githubusercontent.com/OPCFoundation/UA-Nodeset/v1.04/Schema/Opc.Ua.NodeSet2.Services.xml</url> <unpack>false</unpack> <outputDirectory>${project.build.directory}/downloads</outputDirectory> <outputFileName>Opc.Ua.NodeSet2.Services.xml</outputFileName> @@ -104,7 +106,7 @@ <goal>wget</goal> </goals> <configuration> - <url>https://opcfoundation.org/UA/schemas/1.04/Opc.Ua.NodeIds.Services.csv</url> + <url>https://raw.githubusercontent.com/OPCFoundation/UA-Nodeset/v1.04/Schema/Opc.Ua.NodeIds.Services.csv</url> <unpack>false</unpack> <outputDirectory>${project.build.directory}/downloads</outputDirectory> <outputFileName>Opc.Ua.NodeIds.Services.csv</outputFileName> diff --git a/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec b/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec index fa1e47e..d83dcd6 100644 --- a/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec +++ b/protocols/opcua/src/main/resources/protocols/opcua/opcua.mspec @@ -36,10 +36,6 @@ [simple int 32 'maxChunkCount'] [simple PascalString 'endpoint'] ] - ['HEL','true' OpcuaHelloResponse - ] - ['ACK','false' OpcuaAcknowledgeRequest - ] ['ACK','true' OpcuaAcknowledgeResponse [simple string '8' 'chunk'] [implicit int 32 'messageSize' 'lengthInBytes'] @@ -49,10 +45,6 @@ [simple int 32 'maxMessageSize'] [simple int 32 'maxChunkCount'] ] - ['ERR','false' OpcuaErrorRequest - ] - ['ERR','true' OpcuaErrorResponse - ] ['OPN','false' OpcuaOpenRequest [simple string '8' 'chunk'] [implicit int 32 'messageSize' 'lengthInBytes'] @@ -84,8 +76,6 @@ [simple int 32 'requestId'] [simple OpcuaMessage 'message'] ] - ['CLO','true' OpcuaCloseResponse - ] ['MSG','false' OpcuaMessageRequest [simple string '8' 'chunk'] [implicit int 32 'messageSize' 'lengthInBytes'] diff --git a/protocols/opcua/src/main/xslt/opc-types.xsl b/protocols/opcua/src/main/xslt/opc-types.xsl index 0bd8728..65d491d 100644 --- a/protocols/opcua/src/main/xslt/opc-types.xsl +++ b/protocols/opcua/src/main/xslt/opc-types.xsl @@ -217,25 +217,8 @@ <xsl:apply-templates select="/opc:TypeDictionary/opc:EnumeratedType[@Name='NodeIdType']"/> ] -[type 'TwoByteNodeId' - [simple uint 8 'identifier'] -] - -[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' [simple uint 16 'namespaceIndex'] @@ -384,55 +367,59 @@ [array bit 'arrayDimensions' count 'noOfArrayDimensions == null ? 0 : noOfArrayDimensions'] ] - - -[discriminatedType 'NodeId' - [reserved int 2 '0x00'] - [simple NodeIdType 'nodeIdType'] - [typeSwitch 'nodeIdType' - ['NodeIdType.nodeIdTypeTwoByte' NodeIdTwoByte - [simple TwoByteNodeId 'id'] +[type 'NodeIdTypeDefinition' [NodeIdType 'nodeType'] + [implicit nodeIdType 'type' 'nodeType'] + [typeSwitch 'nodeType' + ['nodeIdTypeTwoByte' NodeIdTwoByte + [simple uint 8 'namespaceIndex'] + [simple uint 8 'identifier'] ] - ['NodeIdType.nodeIdTypeFourByte' NodeIdFourByte + ['nodeIdTypeFourByte' NodeIdFourByte + [simple uint 8 'namespaceIndex'] [simple FourByteNodeId 'id'] ] - ['NodeIdType.nodeIdTypeNumeric' NodeIdNumeric + ['nodeIdTypeNumeric' NodeIdNumeric + [simple uint 16 'namespaceIndex'] [simple NumericNodeId 'id'] ] - ['NodeIdType.nodeIdTypeString' NodeIdString + ['nodeIdTypeString' NodeIdString + [simple uint 16 'namespaceIndex'] [simple StringNodeId 'id'] ] - ['NodeIdType.nodeIdTypeGuid' NodeIdGuid + ['nodeIdTypeGuid' NodeIdGuid + [simple uint 16 'namespaceIndex'] [simple GuidNodeId 'id'] ] - ['NodeIdType.nodeIdTypeByteString' NodeIdByteString + ['nodeIdTypeByteString' NodeIdByteString + [simple uint 16 'namespaceIndex'] [simple ByteStringNodeId 'id'] ] ] + +[discriminatedType 'NodeId' + [reserved int 2 '0x00'] + [implicit NodeIdType 'nodeId.nodeType'] + [simple NodeIdTypeDefinition 'nodeId'] ] [type 'ExpandedNodeId' [simple bit 'namespaceURISpecified'] [simple bit 'serverIndexSpecified'] - [simple NodeIdType 'nodeIdType'] - [optional TwoByteNodeId 'idTwoByte' 'nodeIdType == NodeIdType.nodeIdTypeTwoByte'] - [optional FourByteNodeId 'idFourByte' 'nodeIdType == NodeIdType.nodeIdTypeFourByte'] - [optional NumericNodeId 'idNumeric' 'nodeIdType == NodeIdType.nodeIdTypeNumeric'] - [optional StringNodeId 'idString' 'nodeIdType == NodeIdType.nodeIdTypeString'] - [optional GuidNodeId 'idGuid' 'nodeIdType == NodeIdType.nodeIdTypeGuid'] - [optional ByteStringNodeId 'idByteString' 'nodeIdType == NodeIdType.nodeIdTypeByteString'] + [implicit NodeIdType 'nodeId.nodeType'] + [simple NodeIdTypeDefinition 'nodeId'] [optional PascalString 'namespaceURI' 'namespaceURISpecified'] [optional uint 32 'serverIndex' 'serverIndexSpecified'] ] [discriminatedType 'ExtensionObject' //A serialized object prefixed with its data type identifier. - [discriminator ExpandedNodeId 'nodeId'] + [simple ExpandedNodeId 'nodeId'] + [virtual string '-1' 'identifier' 'nodeId.id'] [simple uint 8 'encodingMask'] [optional int 32 'bodyLength' 'encodingMask > 0'] [array int 8 'body' count 'bodyLength == null ? 0 : bodyLength'] - [typeSwitch 'nodeId.nodeIdType','nodeId.idTwoByte.identifier' - ['NodeIdType.nodeIdTypeTwoByte','811' DataChangeNotification + [typeSwitch 'identifier' + ['811' DataChangeNotification <xsl:apply-templates select="/opc:TypeDictionary/opc:StructuredType[@Name='DataChangeNotification']"/> ] ]
