Search code examples
eclipseopc-uamilo

Connecting to an OPC-UA server using Eclipse Milo, fails on BadHostUnknown


I am new to OPC-UA and Eclipse Milo and I am trying to construct a client that can connect to the OPC-UA server of a machine we have just acquired.

I have been able to set up a simple OPC-UA server on my laptop by using this python tutorial series: https://www.youtube.com/watch?v=NbKeBfK3pfk. Additionally, I have been able to use the Eclipse Milo examples to run the subscription example successfully to read some values from this server.

However, I have been having difficulty connecting to the OPC-UA server of the machine we have just received. I have successfully connected to this server using the UaExpert client, but we want to build our own client using Eclipse Milo. I can see that some warnings come up when using UaExpert to connect to the server which appear to give clues about the issue but I have too little experience in server-client communications/OPC-UA and would appreciate some help. I will explain what happens when I use the UaExpert client as I have been using this to try and diagnose what is going on.

I notice that when I first launch UaExpert I get the following errors which could be relevant:

Discovery FindServersOnNetwork on opc.tcp://localhost:4840 failed (BadTimeout), falling back to FindServers
Discovery FindServers on opc.tpc://localhost:4840 failed (BadTimeout)
Discovery GetEndpoints on opc.tcp://localhost:4840 failed

I am really new to networking so not sure exactly what this means.

I will outline the process I have followed when trying to get the SubscriptionExample of Eclipse Milo working with this machine's server. Firstly, I change the getEndpointUrl() method to the ip address of the device we are using: return "opc.tcp://11.23.1.1:4840". I can successfully ping the device using ping 11.23.1.1 from my laptop. When I try to run the SubscriptionExample with this address I get the following error:

[NonceUtilSecureRandom] INFO  o.e.m.o.stack.core.util.NonceUtil - SecureRandom seeded in 0ms.
18:36:23.879 [main] ERROR o.e.m.e.client.ClientExampleRunner - Error running client example: java.net.UnknownHostException: br-automation
java.util.concurrent.ExecutionException: java.net.UnknownHostException: br-automation
    at java.util.concurrent.CompletableFuture.reportGet(Unknown Source)
    at java.util.concurrent.CompletableFuture.get(Unknown Source)
    at org.eclipse.milo.examples.client.SubscriptionExample.run(SubscriptionExample.java:50)
    at org.eclipse.milo.examples.client.ClientExampleRunner.run(ClientExampleRunner.java:120)
    at org.eclipse.milo.examples.client.SubscriptionExample.main(SubscriptionExample.java:42)
Caused by: java.net.UnknownHostException: br-automation
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$2.lookupAllHostAddr(Unknown Source)
    at java.net.InetAddress.getAddressesFromNameService(Unknown Source)
    at java.net.InetAddress.getAllByName0(Unknown Source)
    at java.net.InetAddress.getAllByName(Unknown Source)
    at java.net.InetAddress.getAllByName(Unknown Source)
    at java.net.InetAddress.getByName(Unknown Source)
    at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:148)
    at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:145)
    at java.security.AccessController.doPrivileged(Native Method)
    at io.netty.util.internal.SocketUtils.addressByName(SocketUtils.java:145)
    at io.netty.resolver.DefaultNameResolver.doResolve(DefaultNameResolver.java:43)
    at io.netty.resolver.SimpleNameResolver.resolve(SimpleNameResolver.java:63)
    at io.netty.resolver.SimpleNameResolver.resolve(SimpleNameResolver.java:55)
    at io.netty.resolver.InetSocketAddressResolver.doResolve(InetSocketAddressResolver.java:57)
    at io.netty.resolver.InetSocketAddressResolver.doResolve(InetSocketAddressResolver.java:32)
    at io.netty.resolver.AbstractAddressResolver.resolve(AbstractAddressResolver.java:108)
    at io.netty.bootstrap.Bootstrap.doResolveAndConnect0(Bootstrap.java:200)
    at io.netty.bootstrap.Bootstrap.access$000(Bootstrap.java:46)
    at io.netty.bootstrap.Bootstrap$1.operationComplete(Bootstrap.java:180)
    at io.netty.bootstrap.Bootstrap$1.operationComplete(Bootstrap.java:166)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:577)
    at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:551)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:490)
    at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:615)
    at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:604)
    at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:104)
    at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84)
    at io.netty.channel.AbstractChannel$AbstractUnsafe.safeSetSuccess(AbstractChannel.java:984)
    at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:504)
    at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:417)
    at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:474)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at java.lang.Thread.run(Unknown Source)
18:36:23.881 [ForkJoinPool.commonPool-worker-1] ERROR o.e.m.e.client.ClientExampleRunner - Error running example: java.net.UnknownHostException: br-automation
java.util.concurrent.ExecutionException: java.net.UnknownHostException: br-automation
    at java.util.concurrent.CompletableFuture.reportGet(Unknown Source)
    at java.util.concurrent.CompletableFuture.get(Unknown Source)
    at org.eclipse.milo.examples.client.SubscriptionExample.run(SubscriptionExample.java:50)
    at org.eclipse.milo.examples.client.ClientExampleRunner.run(ClientExampleRunner.java:120)
    at org.eclipse.milo.examples.client.SubscriptionExample.main(SubscriptionExample.java:42)
Caused by: java.net.UnknownHostException: br-automation
    at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
    at java.net.InetAddress$2.lookupAllHostAddr(Unknown Source)
    at java.net.InetAddress.getAddressesFromNameService(Unknown Source)
    at java.net.InetAddress.getAllByName0(Unknown Source)
    at java.net.InetAddress.getAllByName(Unknown Source)
    at java.net.InetAddress.getAllByName(Unknown Source)
    at java.net.InetAddress.getByName(Unknown Source)
    at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:148)
    at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:145)
    at java.security.AccessController.doPrivileged(Native Method)
    at io.netty.util.internal.SocketUtils.addressByName(SocketUtils.java:145)
    at io.netty.resolver.DefaultNameResolver.doResolve(DefaultNameResolver.java:43)
    at io.netty.resolver.SimpleNameResolver.resolve(SimpleNameResolver.java:63)
    at io.netty.resolver.SimpleNameResolver.resolve(SimpleNameResolver.java:55)
    at io.netty.resolver.InetSocketAddressResolver.doResolve(InetSocketAddressResolver.java:57)
    at io.netty.resolver.InetSocketAddressResolver.doResolve(InetSocketAddressResolver.java:32)
    at io.netty.resolver.AbstractAddressResolver.resolve(AbstractAddressResolver.java:108)
    at io.netty.bootstrap.Bootstrap.doResolveAndConnect0(Bootstrap.java:200)
    at io.netty.bootstrap.Bootstrap.access$000(Bootstrap.java:46)
    at io.netty.bootstrap.Bootstrap$1.operationComplete(Bootstrap.java:180)
    at io.netty.bootstrap.Bootstrap$1.operationComplete(Bootstrap.java:166)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:577)
    at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:551)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:490)
    at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:615)
    at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:604)
    at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:104)
    at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84)
    at io.netty.channel.AbstractChannel$AbstractUnsafe.safeSetSuccess(AbstractChannel.java:984)
    at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:504)
    at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:417)
    at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:474)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at java.lang.Thread.run(Unknown Source)

When using UaExpert, "opc.tcp://11.23.1.1:4840" is the address of the server that I input when adding a new server when using Custom Discovery. When I enter this, a device appears as a dropdown of this server called B&R Embedded OPC-UA Server as the OPC-UA server is hosted on a B&R device in the machine. When I select this device to connect to, I get the following message:

The hostname of the discovery URL used to call GetEndpoints (br-automation) was replaced by the hostname used to call FindServers (11.23.1.1). Do you also want to replace the hostnames of the EndpointURLs with this hostname?

I have to accept this message for the server to be found, but I am confused exactly what is going on. I assume there is a difference in the endpoint used to find the server and the endpoint used for something else? I have found the resources online very difficult to understand. In the UaExpert logs there are three lines of logs in a row which report "Adding Url: ocp.tcp://br-automation:4840". It also then reports the endpoint: "ocp.tcp://br-automation:4840", the application Uri and the security policy (none). If I try change the address in the client's getEndpointUrl method to ocp.tcp://br-automation:4840 then I get the following error:

[main] INFO  o.e.m.opcua.sdk.client.OpcUaClient - Eclipse Milo OPC UA Client SDK version: 0.4.3-SNAPSHOT
18:37:46.035 [main] ERROR o.e.m.e.client.ClientExampleRunner - Error getting client: java.util.concurrent.ExecutionException: java.net.UnknownHostException: br-automation
org.eclipse.milo.opcua.stack.core.UaException: java.util.concurrent.ExecutionException: java.net.UnknownHostException: br-automation
    at org.eclipse.milo.opcua.sdk.client.OpcUaClient.lambda$create$1(OpcUaClient.java:204)
    at java.util.Optional.orElseGet(Unknown Source)
    at org.eclipse.milo.opcua.sdk.client.OpcUaClient.create(OpcUaClient.java:204)
    at org.eclipse.milo.opcua.sdk.client.OpcUaClient.create(OpcUaClient.java:201)
    at org.eclipse.milo.examples.client.ClientExampleRunner.createClient(ClientExampleRunner.java:73)
    at org.eclipse.milo.examples.client.ClientExampleRunner.run(ClientExampleRunner.java:94)
    at org.eclipse.milo.examples.client.SubscriptionExample.main(SubscriptionExample.java:42)
Caused by: java.util.concurrent.ExecutionException: java.net.UnknownHostException: br-automation
    at java.util.concurrent.CompletableFuture.reportGet(Unknown Source)
    at java.util.concurrent.CompletableFuture.get(Unknown Source)
    at org.eclipse.milo.opcua.sdk.client.OpcUaClient.create(OpcUaClient.java:180)
    ... 4 common frames omitted
Caused by: java.net.UnknownHostException: br-automation
    at java.net.InetAddress.getAllByName0(Unknown Source)
    at java.net.InetAddress.getAllByName(Unknown Source)
    at java.net.InetAddress.getAllByName(Unknown Source)
    at java.net.InetAddress.getByName(Unknown Source)
    at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:148)
    at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:145)
    at java.security.AccessController.doPrivileged(Native Method)
    at io.netty.util.internal.SocketUtils.addressByName(SocketUtils.java:145)
    at io.netty.resolver.DefaultNameResolver.doResolve(DefaultNameResolver.java:43)
    at io.netty.resolver.SimpleNameResolver.resolve(SimpleNameResolver.java:63)
    at io.netty.resolver.SimpleNameResolver.resolve(SimpleNameResolver.java:55)
    at io.netty.resolver.InetSocketAddressResolver.doResolve(InetSocketAddressResolver.java:57)
    at io.netty.resolver.InetSocketAddressResolver.doResolve(InetSocketAddressResolver.java:32)
    at io.netty.resolver.AbstractAddressResolver.resolve(AbstractAddressResolver.java:108)
    at io.netty.bootstrap.Bootstrap.doResolveAndConnect0(Bootstrap.java:200)
    at io.netty.bootstrap.Bootstrap.access$000(Bootstrap.java:46)
    at io.netty.bootstrap.Bootstrap$1.operationComplete(Bootstrap.java:180)
    at io.netty.bootstrap.Bootstrap$1.operationComplete(Bootstrap.java:166)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:577)
    at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:551)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:490)
    at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:615)
    at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:604)
    at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:104)
    at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84)
    at io.netty.channel.AbstractChannel$AbstractUnsafe.safeSetSuccess(AbstractChannel.java:984)
    at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:504)
    at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:417)
    at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:474)
    at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
    at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at java.lang.Thread.run(Unknown Source)

I don't know if this is enough information to diagnose the problem, but I would appreciate any help on how I can get the Eclipse Milo server to perform the same process and connect to the machine's server.


Solution

  • The issue is that the computer you're running the client on can't resolve the hostname "br-automation" into an IP address.

    The solution if you can't configure your server to return an IP address instead is to manually rebuild the EndpointDescriptions you get from the GetEndpoints service call so they have an endpoint URL that contains the IP address instead of the hostname. This is what UaExpert is doing behind the scenes when it warns you about replacing the hostname.

    You can use EndpointUtil#updateUrl to build a new EndpointDescription before it gets passed to the OpcUaClientConfig.