0
votes

I'm testing Eclipse Milo (Version 0.1.5) to communicate as a client with the OPC UA server of a TwinCAT PLC. My java program acts as a kind of middleware. It reads structures from a TwinCAT OPC UA server, puts their values into a JSON and sends it to an other server.

For testing I created in the PLC a sample struct with two variables:
stSimpleStruct (Structure definiend in PLC)
- bVar1 (boolean)
- fVar2 (float)
Picture of Struct in TwinCAT

If I read the node, the value is an ExtensionObject encoded as ByteString. The values of the structure variables (bVar1 and fVar2) should be read and put into a JSON object. So the result is something like this:

{
    “bVar1” : false,
    “fVar2” : 0
}

The structure above is just an example. The structures to be read are only known at runtime. How can I decode the binary ExtensionObject to get access to the values of the structure variables?

Here is my code:

 // Get endpoints
 String endpointURL = "opc.tcp://172.20.1.1:4840";
 EndpointDescription[] endpoints = UaTcpStackClient.getEndpoints(endpointURL).get();
 logger.info("Available endpoint:");
 for (EndpointDescription endpoint : endpoints)
 {
     logger.info("{} Security: {}", endpoint.getEndpointUrl(), endpoint.getSecurityPolicyUri());
 }
 // Chose endpoint
 SecurityPolicy securityPolicy = SecurityPolicy.None;
 EndpointDescription endpoint = Arrays.stream(endpoints)
     .filter(e -> e.getSecurityPolicyUri().equals(securityPolicy.getSecurityPolicyUri()))
     .findFirst()
     .orElseThrow(() -> new Exception("No desired endpoints returned"));
 logger.info("Using endpoint: {} [{}]", endpoint.getEndpointUrl(), SecurityPolicy.None);
 // Create client config
 OpcUaClientConfig config = OpcUaClientConfig.builder()
     .setApplicationName(LocalizedText.english("TestApplication"))
     .setEndpoint(endpoint)
     .setRequestTimeout(uint(5000))
     .build();
 OpcUaClient client = new OpcUaClient(config);
 // Synchronous connect
 client.connect().get();
 // Read struct
 NodeId nodeId = new NodeId(4, "MAIN.stSimpleStruct");
 VariableNode node = client.getAddressSpace().createVariableNode(nodeId);
 DataValue value = node.readValue().get();
 ExtensionObject extensionObject = (ExtensionObject) value.getValue().getValue();
1
Welcome to Stack Overflow! Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a minimal reproducible example. Use the "edit" link to improve your question - do not add more information via comments. Thanks! - GhostCat
Dont link to external sites with screen shots or what not. Include your source code as well formatted text into the question! - GhostCat
also you can add screenshot directly to your question - Ali Ezzat Odeh
Thanks for the suggestions, I tried to improve the question. - M_S

1 Answers

0
votes

Custom DataTypes aren't supported by Milo right now.

I have working code that can read the DataTypeDictionary nodes in the server and build custom codecs at runtime that get registered with the DataTypeManager, but if, when, and how this code is going to be released still hasn't been decided. In any case, it's written against the development 0.2.0 branch of Milo, which has changes to accommodate custom DataTypes, so it won't be available until at least then.

You can email me, the list, or stop by the gitter.im channel if you want to discuss this further.