This is an automated email from the ASF dual-hosted git repository. cdutz pushed a commit to branch feature/plc4c in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit 3811a17a03e5850154abde9becdef3ff26f2fba5 Author: hutcheb <[email protected]> AuthorDate: Tue Jan 19 06:54:51 2021 -0500 Re-Wrote OPC UA server -> Milo Interface Outstanding issue with PLC4X comms failure when adding tag that isn't valid. --- plc4j/integrations/opcua-server/pom.xml | 5 - .../apache/plc4x/java/opcuaserver/OPCUAServer.java | 165 ++++++++++----------- .../opcuaserver/backend/Plc4xCommunication.java | 63 ++------ .../java/opcuaserver/backend/Plc4xNamespace.java | 104 ++++--------- .../opcuaserver/configuration/Configuration.java | 7 - .../plc4x/java/opcuaserver/OpcuaPlcDriverTest.java | 75 ++++------ .../opcua-server/src/test/resources/config.yml | 1 - 7 files changed, 148 insertions(+), 272 deletions(-) diff --git a/plc4j/integrations/opcua-server/pom.xml b/plc4j/integrations/opcua-server/pom.xml index ede65e2..3313a16 100644 --- a/plc4j/integrations/opcua-server/pom.xml +++ b/plc4j/integrations/opcua-server/pom.xml @@ -51,11 +51,6 @@ <scope>test</scope> </dependency> - <dependency> - <groupId>com.google.guava</groupId> - <artifactId>guava</artifactId> - <version>${guava.version}</version> - </dependency> <dependency> <groupId>org.eclipse.milo</groupId> diff --git a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/OPCUAServer.java b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/OPCUAServer.java index 2aa6bca..1c6ddcb 100644 --- a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/OPCUAServer.java +++ b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/OPCUAServer.java @@ -21,11 +21,10 @@ package org.apache.plc4x.java.opcuaserver; import java.io.File; import java.io.FileInputStream; +import java.net.InetAddress; import java.security.*; import java.security.cert.X509Certificate; -import java.util.ArrayList; import java.util.LinkedHashSet; -import java.util.List; import java.util.Set; import java.util.concurrent.CompletableFuture; @@ -46,7 +45,6 @@ import org.eclipse.milo.opcua.sdk.server.api.config.OpcUaServerConfig; import org.eclipse.milo.opcua.sdk.server.identity.CompositeValidator; import org.eclipse.milo.opcua.sdk.server.identity.UsernameIdentityValidator; import org.eclipse.milo.opcua.sdk.server.identity.X509IdentityValidator; -import org.eclipse.milo.opcua.sdk.server.util.HostnameUtil; import org.eclipse.milo.opcua.stack.core.StatusCodes; import org.eclipse.milo.opcua.stack.core.UaRuntimeException; import org.eclipse.milo.opcua.stack.core.security.DefaultCertificateManager; @@ -58,15 +56,11 @@ import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText; import org.eclipse.milo.opcua.stack.core.types.enumerated.MessageSecurityMode; import org.eclipse.milo.opcua.stack.core.types.structured.BuildInfo; import org.eclipse.milo.opcua.stack.core.util.CertificateUtil; -import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator; -import org.eclipse.milo.opcua.stack.core.util.SelfSignedHttpsCertificateBuilder; import org.eclipse.milo.opcua.stack.server.EndpointConfiguration; import org.eclipse.milo.opcua.stack.server.security.DefaultServerCertificateValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static com.google.common.collect.Lists.newArrayList; -import org.apache.commons.lang3.RandomStringUtils; import static org.eclipse.milo.opcua.sdk.server.api.config.OpcUaServerConfig.USER_TOKEN_POLICY_ANONYMOUS; import static org.eclipse.milo.opcua.sdk.server.api.config.OpcUaServerConfig.USER_TOKEN_POLICY_USERNAME; import static org.eclipse.milo.opcua.sdk.server.api.config.OpcUaServerConfig.USER_TOKEN_POLICY_X509; @@ -205,10 +199,9 @@ public class OPCUAServer { } public static void main(String[] args) throws Exception { - OPCUAServer server = new OPCUAServer(args); - server.startup().get(); - final CompletableFuture<Void> future = new CompletableFuture<>(); - Runtime.getRuntime().addShutdownHook(new Thread(() -> future.complete(null))); + OPCUAServer serverInit = new OPCUAServer(args); + serverInit.getServer().startup().get(); + CompletableFuture<Void> future = new CompletableFuture<>(); future.get(); } @@ -220,21 +213,18 @@ public class OPCUAServer { readCommandLineArgs(args); - File securityTempDir = new File(config.getDir(), "security"); if (!securityTempDir.exists() && !securityTempDir.mkdirs()) { logger.error("Unable to create directory please confirm folder permissions on " + securityTempDir.toString()); System.exit(1); } - logger.info("security dir: {}", securityTempDir.getAbsolutePath()); + logger.info("Security Directory is: {}", securityTempDir.getAbsolutePath()); // File pkiDir = FileSystems.getDefault().getPath(config.getDir()).resolve("pki").toFile(); DefaultTrustListManager trustListManager = new DefaultTrustListManager(pkiDir); - logger.info("pki dir: {}", pkiDir.getAbsolutePath()); - - DefaultServerCertificateValidator certificateValidator = - new DefaultServerCertificateValidator(trustListManager); + logger.info("Certificate directory is: {}, Please move certificates from the reject dir to the trusted directory to allow encrypted access", pkiDir.getAbsolutePath()); + DefaultServerCertificateValidator certificateValidator = new DefaultServerCertificateValidator(trustListManager); UsernameIdentityValidator identityValidator = new UsernameIdentityValidator( true, @@ -251,7 +241,7 @@ public class OPCUAServer { File serverKeyStore = securityTempDir.toPath().resolve(certificateFileName).toFile(); - X509IdentityValidator x509IdentityValidator = new X509IdentityValidator(c -> true); //Fix this + X509IdentityValidator x509IdentityValidator = new X509IdentityValidator(c -> true); CertificateKeyPair certificate = null; if (!serverKeyStore.exists()) { @@ -262,7 +252,6 @@ public class OPCUAServer { certificate = Encryption.generateCertificate(); } else { logger.info("Loading KeyStore at {}", serverKeyStore); - keyStore.load(new FileInputStream(serverKeyStore), passwordConfig.getSecurityPassword().toCharArray()); String alias = keyStore.aliases().nextElement(); KeyPair kp = new KeyPair((PublicKey) keyStore.getCertificate(alias).getPublicKey(), @@ -276,7 +265,75 @@ public class OPCUAServer { StatusCodes.Bad_ConfigurationError, "certificate is missing the application URI")); - Set<EndpointConfiguration> endpointConfigurations = createEndpointConfigurations(certificate.getCertificate()); + Set<EndpointConfiguration> endpointConfigurations = new LinkedHashSet<>(); + + String hostname = InetAddress.getLocalHost().getHostName(); + + EndpointConfiguration.Builder builder = EndpointConfiguration.newBuilder() + .setBindAddress("0.0.0.0") + .setHostname(hostname) + .setPath("/plc4x") + .setCertificate(certificate.getCertificate()) + .setBindPort(config.getTcpPort()) + .setSecurityMode(MessageSecurityMode.None) + .addTokenPolicies( + USER_TOKEN_POLICY_ANONYMOUS, + USER_TOKEN_POLICY_USERNAME, + USER_TOKEN_POLICY_X509); + + endpointConfigurations.add( + builder.copy() + .setSecurityPolicy(SecurityPolicy.Basic256Sha256) + .setSecurityMode(MessageSecurityMode.SignAndEncrypt) + .build() + ); + + endpointConfigurations.add( + builder.copy() + .setHostname("127.0.0.1") + .setSecurityPolicy(SecurityPolicy.Basic256Sha256) + .setSecurityMode(MessageSecurityMode.SignAndEncrypt) + .build() + ); + + EndpointConfiguration.Builder discoveryBuilder = builder.copy() + .setPath("/discovery") + .setSecurityPolicy(SecurityPolicy.None) + .setSecurityMode(MessageSecurityMode.None); + + endpointConfigurations.add(discoveryBuilder.build()); + + EndpointConfiguration.Builder discoveryLocalBuilder = builder.copy() + .setPath("/discovery") + .setHostname("127.0.0.1") + .setSecurityPolicy(SecurityPolicy.None) + .setSecurityMode(MessageSecurityMode.None); + + endpointConfigurations.add(discoveryLocalBuilder.build()); + + EndpointConfiguration.Builder discoveryLocalPlc4xBuilder = builder.copy() + .setPath("/plc4x/discovery") + .setHostname("127.0.0.1") + .setSecurityPolicy(SecurityPolicy.None) + .setSecurityMode(MessageSecurityMode.None); + + endpointConfigurations.add(discoveryLocalPlc4xBuilder.build()); + + if (!config.getDisableInsecureEndpoint()) { + EndpointConfiguration.Builder noSecurityBuilder = builder.copy() + .setSecurityPolicy(SecurityPolicy.None) + .setTransportProfile(TransportProfile.TCP_UASC_UABINARY); + endpointConfigurations.add(noSecurityBuilder.build()); + } + + //Always add an unsecured endpoint to localhost, this is a work around for Milo throwing an exception if it isn't here. + EndpointConfiguration.Builder noSecurityBuilder = builder.copy() + .setSecurityPolicy(SecurityPolicy.None) + .setHostname("127.0.0.1") + .setTransportProfile(TransportProfile.TCP_UASC_UABINARY) + .setSecurityMode(MessageSecurityMode.None); + endpointConfigurations.add(noSecurityBuilder.build()); + DefaultCertificateManager certificateManager = new DefaultCertificateManager( certificate.getKeyPair(), @@ -307,73 +364,6 @@ public class OPCUAServer { plc4xNamespace.startup(); } - private Set<EndpointConfiguration> createEndpointConfigurations(X509Certificate certificate) { - Set<EndpointConfiguration> endpointConfigurations = new LinkedHashSet<>(); - - List<String> bindAddresses = newArrayList(); - bindAddresses.add("0.0.0.0"); - - List<String> localAddresses = new ArrayList<>(bindAddresses); - - Set<String> hostnames = new LinkedHashSet<>(); - hostnames.add(HostnameUtil.getHostname()); - hostnames.addAll(HostnameUtil.getHostnames("0.0.0.0")); - - for (String bindAddress : bindAddresses) { - for (String hostname : hostnames) { - EndpointConfiguration.Builder builder = EndpointConfiguration.newBuilder() - .setBindAddress(bindAddress) - .setHostname(hostname) - .setPath("/plc4x") - .setCertificate(certificate) - .addTokenPolicies( - USER_TOKEN_POLICY_ANONYMOUS, - USER_TOKEN_POLICY_USERNAME, - USER_TOKEN_POLICY_X509); - - - if (!config.getDisableInsecureEndpoint()) { - EndpointConfiguration.Builder noSecurityBuilder = builder.copy() - .setSecurityPolicy(SecurityPolicy.None) - .setSecurityMode(MessageSecurityMode.None); - endpointConfigurations.add(buildTcpEndpoint(noSecurityBuilder)); - } else { - //Always add an unsecured endpoint to localhost, this is a work around for Milo throwing an exception if it isn't here. - if (hostname.equals("127.0.0.1")) { - EndpointConfiguration.Builder noSecurityBuilder = builder.copy() - .setSecurityPolicy(SecurityPolicy.None) - .setSecurityMode(MessageSecurityMode.None); - endpointConfigurations.add(buildTcpEndpoint(noSecurityBuilder)); - } - } - - // TCP Basic256Sha256 / SignAndEncrypt - endpointConfigurations.add(buildTcpEndpoint( - builder.copy() - .setSecurityPolicy(SecurityPolicy.Basic256Sha256) - .setSecurityMode(MessageSecurityMode.SignAndEncrypt)) - ); - - EndpointConfiguration.Builder discoveryBuilder = builder.copy() - .setPath("/discovery") - .setSecurityPolicy(SecurityPolicy.None) - .setSecurityMode(MessageSecurityMode.None); - - - endpointConfigurations.add(buildTcpEndpoint(discoveryBuilder)); - } - } - - return endpointConfigurations; - } - - private EndpointConfiguration buildTcpEndpoint(EndpointConfiguration.Builder base) { - return base.copy() - .setTransportProfile(TransportProfile.TCP_UASC_UABINARY) - .setBindPort(config.getTcpPort()) - .build(); - } - public OpcUaServer getServer() { return server; } @@ -384,7 +374,6 @@ public class OPCUAServer { public CompletableFuture<OpcUaServer> shutdown() { plc4xNamespace.shutdown(); - return server.shutdown(); } diff --git a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java index 9e32867..1c717c8 100644 --- a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java +++ b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xCommunication.java @@ -19,59 +19,15 @@ package org.apache.plc4x.java.opcuaserver.backend; - import java.lang.reflect.Array; -import java.util.List; import java.util.Arrays; -import java.util.Random; -import java.util.UUID; - -import org.eclipse.milo.opcua.sdk.core.AccessLevel; -import org.eclipse.milo.opcua.sdk.core.Reference; -import org.eclipse.milo.opcua.sdk.core.ValueRank; -import org.eclipse.milo.opcua.sdk.core.ValueRanks; -import org.eclipse.milo.opcua.sdk.server.Lifecycle; -import org.eclipse.milo.opcua.sdk.server.OpcUaServer; import org.eclipse.milo.opcua.sdk.server.api.DataItem; -import org.eclipse.milo.opcua.sdk.server.api.DataTypeDictionaryManager; -import org.eclipse.milo.opcua.sdk.server.api.ManagedNamespaceWithLifecycle; -import org.eclipse.milo.opcua.sdk.server.api.MonitoredItem; -import org.eclipse.milo.opcua.sdk.server.model.nodes.objects.BaseEventTypeNode; -import org.eclipse.milo.opcua.sdk.server.model.nodes.objects.ServerTypeNode; -import org.eclipse.milo.opcua.sdk.server.model.nodes.variables.AnalogItemTypeNode; import org.eclipse.milo.opcua.sdk.server.nodes.filters.AttributeFilterContext; -import org.eclipse.milo.opcua.sdk.server.nodes.UaFolderNode; -import org.eclipse.milo.opcua.sdk.server.nodes.UaMethodNode; -import org.eclipse.milo.opcua.sdk.server.nodes.UaNode; -import org.eclipse.milo.opcua.sdk.server.nodes.UaObjectNode; -import org.eclipse.milo.opcua.sdk.server.nodes.UaObjectTypeNode; -import org.eclipse.milo.opcua.sdk.server.nodes.UaVariableNode; -import org.eclipse.milo.opcua.sdk.server.nodes.factories.NodeFactory; -import org.eclipse.milo.opcua.sdk.server.nodes.filters.AttributeFilters; -import org.eclipse.milo.opcua.sdk.server.util.SubscriptionModel; -import org.eclipse.milo.opcua.stack.core.AttributeId; -import org.eclipse.milo.opcua.stack.core.BuiltinDataType; import org.eclipse.milo.opcua.stack.core.Identifiers; -import org.eclipse.milo.opcua.stack.core.UaException; -import org.eclipse.milo.opcua.stack.core.types.builtin.ByteString; import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue; -import org.eclipse.milo.opcua.stack.core.types.builtin.DateTime; -import org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject; -import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText; import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId; -import org.eclipse.milo.opcua.stack.core.types.builtin.QualifiedName; import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode; import org.eclipse.milo.opcua.stack.core.types.builtin.Variant; -import org.eclipse.milo.opcua.stack.core.types.builtin.XmlElement; -import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger; -import org.eclipse.milo.opcua.stack.core.types.enumerated.StructureType; -import org.eclipse.milo.opcua.stack.core.types.structured.EnumDefinition; -import org.eclipse.milo.opcua.stack.core.types.structured.EnumDescription; -import org.eclipse.milo.opcua.stack.core.types.structured.EnumField; -import org.eclipse.milo.opcua.stack.core.types.structured.Range; -import org.eclipse.milo.opcua.stack.core.types.structured.StructureDefinition; -import org.eclipse.milo.opcua.stack.core.types.structured.StructureDescription; -import org.eclipse.milo.opcua.stack.core.types.structured.StructureField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,15 +37,14 @@ import org.apache.plc4x.java.api.PlcConnection; import org.apache.plc4x.java.api.messages.PlcReadRequest; import org.apache.plc4x.java.api.messages.PlcReadResponse; import org.apache.plc4x.java.api.messages.PlcWriteRequest; -import org.apache.plc4x.java.api.messages.PlcWriteResponse; + import org.apache.plc4x.java.api.types.PlcResponseCode; -import org.apache.plc4x.java.api.value.PlcValue; + import org.apache.plc4x.java.utils.connectionpool.*; import org.apache.plc4x.java.api.exceptions.PlcConnectionException; -import org.apache.plc4x.java.api.exceptions.PlcRuntimeException; + import org.apache.plc4x.java.api.model.PlcField; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeUnit; @@ -98,10 +53,8 @@ import java.util.HashMap; import java.math.BigInteger; -import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.ubyte; -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; -import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.ushort; + public class Plc4xCommunication { @@ -118,6 +71,14 @@ public class Plc4xCommunication { driverManager = new PooledPlcDriverManager(); } + public PlcDriverManager getDriverManager() { + return driverManager; + } + + public void setDriverManager(PlcDriverManager driverManager) { + this.driverManager = driverManager; + } + public PlcField getField(String tag, String connectionString) throws PlcConnectionException { return driverManager.getDriver(connectionString).prepareField(tag); } diff --git a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java index 654ac4b..12e3313 100644 --- a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java +++ b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/backend/Plc4xNamespace.java @@ -19,141 +19,86 @@ package org.apache.plc4x.java.opcuaserver.backend; -import org.apache.plc4x.java.opcuaserver.*; - import java.lang.reflect.Array; import java.util.Arrays; import java.util.List; -import java.util.Random; -import java.util.UUID; import org.apache.plc4x.java.opcuaserver.configuration.Configuration; import org.apache.plc4x.java.opcuaserver.configuration.DeviceConfiguration; import org.apache.plc4x.java.opcuaserver.configuration.Tag; +import org.apache.plc4x.java.utils.connectionpool.PooledPlcDriverManager; import org.eclipse.milo.opcua.sdk.core.AccessLevel; import org.eclipse.milo.opcua.sdk.core.Reference; import org.eclipse.milo.opcua.sdk.core.ValueRank; -import org.eclipse.milo.opcua.sdk.core.ValueRanks; -import org.eclipse.milo.opcua.sdk.server.Lifecycle; import org.eclipse.milo.opcua.sdk.server.OpcUaServer; import org.eclipse.milo.opcua.sdk.server.api.DataItem; import org.eclipse.milo.opcua.sdk.server.api.DataTypeDictionaryManager; import org.eclipse.milo.opcua.sdk.server.api.ManagedNamespaceWithLifecycle; import org.eclipse.milo.opcua.sdk.server.api.MonitoredItem; -import org.eclipse.milo.opcua.sdk.server.model.nodes.objects.BaseEventTypeNode; -import org.eclipse.milo.opcua.sdk.server.model.nodes.objects.ServerTypeNode; -import org.eclipse.milo.opcua.sdk.server.model.nodes.variables.AnalogItemTypeNode; import org.eclipse.milo.opcua.sdk.server.nodes.UaFolderNode; -import org.eclipse.milo.opcua.sdk.server.nodes.UaMethodNode; -import org.eclipse.milo.opcua.sdk.server.nodes.UaNode; -import org.eclipse.milo.opcua.sdk.server.nodes.UaObjectNode; -import org.eclipse.milo.opcua.sdk.server.nodes.UaObjectTypeNode; import org.eclipse.milo.opcua.sdk.server.nodes.UaVariableNode; -import org.eclipse.milo.opcua.sdk.server.nodes.factories.NodeFactory; import org.eclipse.milo.opcua.sdk.server.nodes.filters.AttributeFilters; import org.eclipse.milo.opcua.sdk.server.util.SubscriptionModel; -import org.eclipse.milo.opcua.stack.core.AttributeId; -import org.eclipse.milo.opcua.stack.core.BuiltinDataType; import org.eclipse.milo.opcua.stack.core.Identifiers; -import org.eclipse.milo.opcua.stack.core.UaException; -import org.eclipse.milo.opcua.stack.core.types.builtin.ByteString; import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue; -import org.eclipse.milo.opcua.stack.core.types.builtin.DateTime; -import org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject; import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText; import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId; -import org.eclipse.milo.opcua.stack.core.types.builtin.QualifiedName; -import org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode; import org.eclipse.milo.opcua.stack.core.types.builtin.Variant; -import org.eclipse.milo.opcua.stack.core.types.builtin.XmlElement; import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger; -import org.eclipse.milo.opcua.stack.core.types.enumerated.StructureType; -import org.eclipse.milo.opcua.stack.core.types.structured.EnumDefinition; -import org.eclipse.milo.opcua.stack.core.types.structured.EnumDescription; -import org.eclipse.milo.opcua.stack.core.types.structured.EnumField; -import org.eclipse.milo.opcua.stack.core.types.structured.Range; -import org.eclipse.milo.opcua.stack.core.types.structured.StructureDefinition; -import org.eclipse.milo.opcua.stack.core.types.structured.StructureDescription; -import org.eclipse.milo.opcua.stack.core.types.structured.StructureField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -import org.apache.plc4x.java.api.model.PlcField; import org.apache.plc4x.java.api.exceptions.PlcConnectionException; - -import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.ubyte; 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; -import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.ushort; + public class Plc4xNamespace extends ManagedNamespaceWithLifecycle { - public static final String NAMESPACE_URI = "urn:eclipse:milo:plc4x:server"; + public static final String APPLICATIONID = "urn:eclipse:milo:plc4x:server"; private Configuration config; - private final Logger logger = LoggerFactory.getLogger(getClass()); - - private volatile Thread eventThread; - private volatile boolean keepPostingEvents = true; - - private final Random random = new Random(); - private final DataTypeDictionaryManager dictionaryManager; - private final SubscriptionModel subscriptionModel; - private Plc4xCommunication plc4xServer; public Plc4xNamespace(OpcUaServer server, Configuration c) { - super(server, NAMESPACE_URI); + super(server, APPLICATIONID); this.config = c; subscriptionModel = new SubscriptionModel(server, this); - dictionaryManager = new DataTypeDictionaryManager(getNodeContext(), NAMESPACE_URI); - + dictionaryManager = new DataTypeDictionaryManager(getNodeContext(), APPLICATIONID); plc4xServer = new Plc4xCommunication(); - getLifecycleManager().addLifecycle(dictionaryManager); getLifecycleManager().addLifecycle(subscriptionModel); - getLifecycleManager().addStartupTask(this::addNodes); } private void addNodes() { for (DeviceConfiguration c: config.getDevices()) { - createAndAddNodes(c); - } - } + NodeId folderNodeId = newNodeId(c.getName()); - private void createAndAddNodes(DeviceConfiguration c) { + UaFolderNode folderNode = new UaFolderNode( + getNodeContext(), + folderNodeId, + newQualifiedName(c.getName()), + LocalizedText.english(c.getName()) + ); - NodeId folderNodeId = newNodeId(c.getName()); + getNodeManager().addNode(folderNode); - UaFolderNode folderNode = new UaFolderNode( - getNodeContext(), - folderNodeId, - newQualifiedName(c.getName()), - LocalizedText.english(c.getName()) - ); + folderNode.addReference(new Reference( + folderNode.getNodeId(), + Identifiers.Organizes, + Identifiers.ObjectsFolder.expanded(), + false + )); - getNodeManager().addNode(folderNode); - - // Make sure our new folder shows up under the server's Objects folder. - folderNode.addReference(new Reference( - folderNode.getNodeId(), - Identifiers.Organizes, - Identifiers.ObjectsFolder.expanded(), - false - )); - - addDynamicNodes(folderNode, c); + addConfiguredNodes(folderNode, c); + } } - private void addDynamicNodes(UaFolderNode rootNode, DeviceConfiguration c) { + private void addConfiguredNodes(UaFolderNode rootNode, DeviceConfiguration c) { final List<Tag> tags = c.getTags(); final String connectionString = c.getConnectionString(); for (int i = 0; i < tags.size(); i++) { @@ -238,6 +183,11 @@ public class Plc4xNamespace extends ManagedNamespaceWithLifecycle { public void onDataItemsCreated(List<DataItem> dataItems) { for (DataItem item : dataItems) { plc4xServer.addField(item); + + if (plc4xServer.getDriverManager() == null) { + plc4xServer.removeField(item); + plc4xServer.setDriverManager(new PooledPlcDriverManager()); + } } subscriptionModel.onDataItemsCreated(dataItems); diff --git a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/configuration/Configuration.java b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/configuration/Configuration.java index 854e8c0..88efb2d 100644 --- a/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/configuration/Configuration.java +++ b/plc4j/integrations/opcua-server/src/main/java/org/apache/plc4x/java/opcuaserver/configuration/Configuration.java @@ -47,9 +47,6 @@ public class Configuration { @JsonProperty private Integer tcpPort = 12686; - @JsonProperty - private Integer httpPort = 8443; - public Configuration() { } @@ -73,10 +70,6 @@ public class Configuration { return tcpPort; } - public Integer getHttpPort() { - return httpPort; - } - public List<DeviceConfiguration> getDevices() { return devices; } diff --git a/plc4j/integrations/opcua-server/src/test/java/org/apache/plc4x/java/opcuaserver/OpcuaPlcDriverTest.java b/plc4j/integrations/opcua-server/src/test/java/org/apache/plc4x/java/opcuaserver/OpcuaPlcDriverTest.java index 256f35f..71f0f05 100644 --- a/plc4j/integrations/opcua-server/src/test/java/org/apache/plc4x/java/opcuaserver/OpcuaPlcDriverTest.java +++ b/plc4j/integrations/opcua-server/src/test/java/org/apache/plc4x/java/opcuaserver/OpcuaPlcDriverTest.java @@ -27,51 +27,46 @@ import org.apache.plc4x.java.api.messages.PlcReadResponse; import org.apache.plc4x.java.api.messages.PlcWriteRequest; import org.apache.plc4x.java.api.messages.PlcWriteResponse; import org.apache.plc4x.java.api.types.PlcResponseCode; -import org.apache.plc4x.java.opcua.connection.OpcuaTcpPlcConnection; import org.junit.jupiter.api.*; import java.math.BigInteger; -import java.util.HashSet; -import java.util.Set; + import org.apache.commons.io.FileUtils; import java.io.File; -import static org.apache.plc4x.java.opcua.OpcuaPlcDriver.INET_ADDRESS_PATTERN; -import static org.apache.plc4x.java.opcua.OpcuaPlcDriver.OPCUA_URI_PATTERN; -import static org.apache.plc4x.java.opcuaserver.UtilsTest.assertMatching; import static org.assertj.core.api.Assertions.fail; /** */ public class OpcuaPlcDriverTest { // Read only variables of milo example server of version 3.6 - private static final String BOOL_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_BOOL"; - private static final String BYTE_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_BYTE"; - private static final String DOUBLE_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_LREAL"; - private static final String FLOAT_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_REAL"; - private static final String INT16_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_INT"; - private static final String INT32_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_DINT"; - private static final String INT64_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_LINT"; - private static final String INTEGER_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_DINT"; - private static final String SBYTE_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_USINT"; - private static final String STRING_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_STRING"; - private static final String UINT16_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_UINT"; - private static final String UINT32_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_UDINT"; - private static final String UINT64_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_ULINT"; - private static final String UINTEGER_IDENTIFIER_READ_WRITE = "ns=2;s=Simulated_OPC_UDINT"; - private static final String DOES_NOT_EXIST_IDENTIFIER_READ_WRITE = "ns=2;i=12512623"; + private static final String BOOL_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_BOOL"; + private static final String BYTE_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_BYTE"; + private static final String DOUBLE_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_LREAL"; + private static final String FLOAT_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_REAL"; + private static final String INT16_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_INT"; + private static final String INT32_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_DINT"; + private static final String INT64_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_LINT"; + private static final String INTEGER_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_DINT"; + private static final String SBYTE_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_USINT"; + private static final String STRING_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_STRING"; + private static final String UINT16_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_UINT"; + private static final String UINT32_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_UDINT"; + private static final String UINT64_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_ULINT"; + private static final String UINTEGER_IDENTIFIER_READ_WRITE = "ns=1;s=Simulated_UDINT"; + private static final String DOES_NOT_EXIST_IDENTIFIER_READ_WRITE = "ns=1;i=12512623"; // At the moment not used in PLC4X or in the OPC UA driver - private static final String BYTE_STRING_IDENTIFIER_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/ByteString"; - private static final String DATE_TIME_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/DateTime"; - private static final String DURATION_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/Duration"; - private static final String GUID_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/Guid"; - private static final String LOCALISED_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/LocalizedText"; - private static final String NODE_ID_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/NodeId"; - private static final String QUALIFIED_NAM_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/QualifiedName"; - private static final String UTC_TIME_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/UtcTime"; - private static final String VARIANT_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/Variant"; - private static final String XML_ELEMENT_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/XmlElement"; + private static final String BYTE_STRING_IDENTIFIER_READ_WRITE = "ns=1;s=HelloWorld/ScalarTypes/ByteString"; + private static final String DATE_TIME_READ_WRITE = "ns=1;s=HelloWorld/ScalarTypes/DateTime"; + private static final String DURATION_READ_WRITE = "ns=1;s=HelloWorld/ScalarTypes/Duration"; + private static final String GUID_READ_WRITE = "ns=1;s=HelloWorld/ScalarTypes/Guid"; + private static final String LOCALISED_READ_WRITE = "ns=1;s=HelloWorld/ScalarTypes/LocalizedText"; + private static final String NODE_ID_READ_WRITE = "ns=1;s=HelloWorld/ScalarTypes/NodeId"; + private static final String QUALIFIED_NAM_READ_WRITE = "ns=1;s=HelloWorld/ScalarTypes/QualifiedName"; + private static final String UTC_TIME_READ_WRITE = "ns=1;s=HelloWorld/ScalarTypes/UtcTime"; + private static final String VARIANT_READ_WRITE = "ns=1;s=HelloWorld/ScalarTypes/Variant"; + private static final String XML_ELEMENT_READ_WRITE = "ns=1;s=HelloWorld/ScalarTypes/XmlElement"; // Address of local milo server private String miloLocalAddress = "127.0.0.1:12673/plc4x"; //Tcp pattern of OPC UA @@ -113,7 +108,6 @@ public class OpcuaPlcDriverTest { @Test public void connectionNoParams(){ - connectionStringValidSet.forEach(connectionAddress -> { String connectionString = connectionAddress; try { @@ -153,8 +147,8 @@ public class OpcuaPlcDriverTest { } @Test - public void readVariables() { - try { + public void readVariables() throws Exception{ + PlcConnection opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress); assert opcuaConnection.isConnected(); @@ -198,14 +192,12 @@ public class OpcuaPlcDriverTest { opcuaConnection.close(); assert !opcuaConnection.isConnected(); - } catch (Exception e) { - fail("Exception during readVariables Test EXCEPTION: " + e.getMessage()); - } + } @Test - public void writeVariables() { - try { + public void writeVariables() throws Exception { + PlcConnection opcuaConnection = new PlcDriverManager().getConnection(tcpConnectionAddress); assert opcuaConnection.isConnected(); @@ -218,7 +210,7 @@ public class OpcuaPlcDriverTest { builder.addItem("Int32", INT32_IDENTIFIER_READ_WRITE, 42); builder.addItem("Int64", INT64_IDENTIFIER_READ_WRITE, 42L); builder.addItem("Integer", INTEGER_IDENTIFIER_READ_WRITE, 42); - builder.addItem("SByte", SBYTE_IDENTIFIER_READ_WRITE + ":SINT", -100); + builder.addItem("SByte", SBYTE_IDENTIFIER_READ_WRITE + ":USINT", 100); builder.addItem("String", STRING_IDENTIFIER_READ_WRITE, "Helllo Toddy!"); builder.addItem("UInt16", UINT16_IDENTIFIER_READ_WRITE + ":UINT", 65535); builder.addItem("UInt32", UINT32_IDENTIFIER_READ_WRITE + ":UDINT", 100); @@ -248,9 +240,6 @@ public class OpcuaPlcDriverTest { opcuaConnection.close(); assert !opcuaConnection.isConnected(); - } catch (Exception e) { - fail("Exception during writeVariables Test EXCEPTION: " + e.getMessage()); - } } } diff --git a/plc4j/integrations/opcua-server/src/test/resources/config.yml b/plc4j/integrations/opcua-server/src/test/resources/config.yml index d0b0cd9..c60002e 100644 --- a/plc4j/integrations/opcua-server/src/test/resources/config.yml +++ b/plc4j/integrations/opcua-server/src/test/resources/config.yml @@ -21,7 +21,6 @@ dir: "target/test-tmp/" name: Plc4x.OPC.UA.Server disableInsecureEndpoint: true tcpPort: 12673 -httpPort: 8445 devices: - name: "Simulated Device" connectionString: "simulated://127.0.0.1"
