Skip to content

Commit

Permalink
WIP dynamic datatype codecs
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinherron committed Sep 6, 2022
1 parent c9d66e4 commit bf98170
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 21 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021 the Eclipse Milo Authors
* Copyright (c) 2022 the Eclipse Milo Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -109,22 +109,24 @@ public void run() {
OpcUaClient client = createClient();

// For the sake of the examples we will create mutual trust between the client and
// server so we can run them with security enabled by default.
// server, so we can run them with security enabled by default.
// If the client example is pointed at another server then the rejected certificate
// will need to be moved from the security "pki/rejected" directory to the
// "pki/trusted/certs" directory.

// Make the example server trust the example client certificate by default.
client.getConfig().getCertificate().ifPresent(
certificate ->
exampleServer.getServer().getConfig().getTrustListManager().addTrustedCertificate(certificate)
);

// Make the example client trust the example server certificate by default.
exampleServer.getServer().getConfig().getCertificateManager().getCertificates().forEach(
certificate ->
trustListManager.addTrustedCertificate(certificate)
);
if (serverRequired && exampleServer != null) {
// Make the example server trust the example client certificate by default.
client.getConfig().getCertificate().ifPresent(
certificate ->
exampleServer.getServer().getConfig().getTrustListManager().addTrustedCertificate(certificate)
);

// Make the example client trust the example server certificate by default.
exampleServer.getServer().getConfig().getCertificateManager().getCertificates().forEach(
certificate ->
trustListManager.addTrustedCertificate(certificate)
);
}

future.whenCompleteAsync((c, ex) -> {
if (ex != null) {
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 the Eclipse Milo Authors
* Copyright (c) 2022 the Eclipse Milo Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -15,6 +15,7 @@
import org.eclipse.milo.opcua.binaryschema.GenericBsdParser;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.dtd.DataTypeDictionarySessionInitializer;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
Expand Down Expand Up @@ -70,4 +71,9 @@ public String getEndpointUrl() {
return "opc.tcp://localhost:48010";
}

@Override
public SecurityPolicy getSecurityPolicy() {
return SecurityPolicy.None;
}

}
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2022 the Eclipse Milo Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/

package org.eclipse.milo.examples.client;

import java.util.concurrent.CompletableFuture;

import org.eclipse.milo.opcua.sdk.client.DataTypeTreeSessionInitializer;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
import org.eclipse.milo.opcua.stack.core.types.builtin.ExtensionObject;
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* An example that shows reading the value of a node whose DataType is a custom structure type.
* <p>
* Requires the Unified Automation CPP Demo server be running and the endpoint URL be pointing to it.
*/
public class UnifiedAutomationReadCustomDataTypeExample2 implements ClientExample {

public static void main(String[] args) throws Exception {
UnifiedAutomationReadCustomDataTypeExample2 example =
new UnifiedAutomationReadCustomDataTypeExample2();

new ClientExampleRunner(example, false).run();
}

private final Logger logger = LoggerFactory.getLogger(getClass());

@Override
public void run(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception {
// DataTypeTree reads DataTypeDefinition attributes while traversing the type hierarchy
// and registers codecs with the client's dynamic DataTypeManager.
client.addSessionInitializer(new DataTypeTreeSessionInitializer());

client.connect().get();

DataValue dataValue = client.readValue(
0.0,
TimestampsToReturn.Neither,
NodeId.parse("ns=2;s=Demo.Static.Scalar.WorkOrder")
).get();

ExtensionObject xo = (ExtensionObject) dataValue.getValue().getValue();

Object value = xo.decode(client.getDynamicSerializationContext());

logger.info("value: {}", value);

future.complete(client);
}

@Override
public String getEndpointUrl() {
// Change this if UaCPPServer is running somewhere other than localhost.
return "opc.tcp://localhost:48010";
}

@Override
public SecurityPolicy getSecurityPolicy() {
return SecurityPolicy.None;
}

}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019 the Eclipse Milo Authors
* Copyright (c) 2022 the Eclipse Milo Authors
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -18,6 +18,8 @@
import org.eclipse.milo.opcua.stack.client.UaStackClient;
import org.eclipse.milo.opcua.stack.core.NodeIds;
import org.eclipse.milo.opcua.stack.core.types.DynamicStructCodec;
import org.eclipse.milo.opcua.stack.core.types.OpcUaDefaultBinaryEncoding;
import org.eclipse.milo.opcua.stack.core.types.OpcUaDefaultXmlEncoding;
import org.eclipse.milo.opcua.stack.core.types.structured.DataTypeDefinition;
import org.eclipse.milo.opcua.stack.core.types.structured.EnumDefinition;
import org.eclipse.milo.opcua.stack.core.types.structured.StructureDefinition;
Expand Down Expand Up @@ -55,21 +57,26 @@ public CompletableFuture<Unit> initialize(UaStackClient stackClient, OpcUaSessio
if (dataType.getBinaryEncodingId() != null) {
stackClient.getDynamicDataTypeManager().registerCodec(
dataType.getBinaryEncodingId(),
codec
codec.asBinaryCodec()
);
stackClient.getDynamicDataTypeManager().registerCodec(
OpcUaDefaultBinaryEncoding.ENCODING_NAME,
dataType.getNodeId(),
codec.asBinaryCodec()
);
}
if (dataType.getXmlEncodingId() != null) {
stackClient.getDynamicDataTypeManager().registerCodec(
dataType.getXmlEncodingId(),
codec
codec.asXmlCodec()
);
}
if (dataType.getJsonEncodingId() != null) {
stackClient.getDynamicDataTypeManager().registerCodec(
dataType.getJsonEncodingId(),
codec
OpcUaDefaultXmlEncoding.ENCODING_NAME,
dataType.getNodeId(),
codec.asXmlCodec()
);
}
// TODO register JSON codec
}
});
} else {
Expand Down
Expand Up @@ -10,7 +10,9 @@

package org.eclipse.milo.opcua.stack.core.types;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.stream.Collectors;

import org.eclipse.milo.opcua.stack.core.types.structured.Structure;

Expand All @@ -26,4 +28,27 @@ public LinkedHashMap<String, Object> getMembers() {
return members;
}

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("DynamicStruct{");
sb.append("members={");
sb.append(joinMembers(members));
sb.append('}');
return sb.toString();
}

private static String joinMembers(LinkedHashMap<String, Object> members) {
return members.entrySet().stream()
.map(e -> {
String k = e.getKey();
Object v = e.getValue();
if (v instanceof Object[]) {
return String.format("%s=%s", k, Arrays.toString((Object[]) v));
} else {
return String.format("%s=%s", k, v);
}
})
.collect(Collectors.joining(", "));
}

}

0 comments on commit bf98170

Please sign in to comment.