赞
踩
开发环境:KEPServerEX-6.x,JDK-8,milo-0.2.4
KEPServerEX下载:https://pan.baidu.com/s/1kbAh46cCYV0JGeXm3kuX5A?pwd=hy71
提取码:hy71(非破解版,可以自行去官网下载,安装过程一直点下一步就好了)
项目代码:UseMilo
参考文章:使用java的milo框架访问OPCUA服务的方法
使用KEPServerEX6,新建通道选择Simulator,进行仿真具体的OPCUA服务器,编写的Java项目是客户端,建立的TCP连接是Java-----KEPServerEX6软件的OPCUA端口号(默认49320),进行读取值。
同时对于服务器还具有其他调式的可能,运行Java项目是其一,或者下载UaExpert、使用KEPServerEX6的
milo项目地址,https://github.com/eclipse/milo
milo组件库,分为三个大部分:
安装完成后,找到运行图标,右击打开设置---用户管理器---在Administrators下添加新用户,
记下账户名、密码(14位),后续代码使用用户认证需要用到。
回到桌面任务栏,继续右击运行图标,打开OPC UA配置---服务器端点---双击黑色的服务器端点
本地测试时,网络适配器选择仅限本地主机。
访问地址(使用默认的就好),和安全策略(推荐像下图配置)都会具体在代码中体现。
打开KEPServerEX6界面
通道类型选择Simulator
自由设置通道名字、设备名字,但注意使用英文,否则可能出现连接上了读取不到tag值的问题。
之后一直点击下一步即可。
在创立出来的通道(你设置的名字)上,右击选择新建设备。
之后一直点击下一步即可。
单击新建的设备,在空白界面右击选择新建标记。
填入标记名称,地址
值的Quality应该显示为良好。
可以右击具体的标签项,选择Synchronous Write进行修改值内容。
需要注意的是,使用自己KEPServerEX6的客户端连接服务器,可能也需要进行客户端信任。
右击运行图标----OPCUA配置,受信任的客户端,点击列表中被红色叉标记的项,点击信任。
回到KEPServerEX6软件的主界面,右击项目,选择属性。
使用KEPServerEX6创建的通道我们选择了Simulator,作为服务器的通道。他的默认的地址空间为2,即项目中读取时填入的NodeID的namespaceindex为2。我们通过下面的操作也可以看得到。
我们当然也可以右击项目的连接性,再新建一个通道,通道类型选择OPCUA Client,之后依旧使用英文通道名、设备名,不过需要注意的是:
创建OPCUA Client这个通道作为的是一个客户端,因此需要写入连接的服务器的url,我们连接到就是另一个通道,所以使用,opc.tcp://localhost:49320。安全策略也需要跟服务器的保持一致。
同时还需要输入我们在前面第一节新建的用户名账号和密码,进行用户认证,让服务器放行。
之后下一步、完成。
之后对该通道新建设备,输入英文设备名,之后一直下一步,直到可以导入项。
点击导入,就会自动使用刚刚新建通道的时候填入的rul、安全策略、用户名认证进行连接,之后读取里面的值,你可以具体选择一些项进行导入。之后我们就可以在新建的设备上看到他们。注意看,默认的ns确实是2,具体的indentifers名组成为:通道名.设备名.标签名。
这时候就会生成一个客户端,需要驱动进行运行,保持客户端的活性,这是软件官方的付费功能,只能免费运行两小时,之后就会被取消链接。
项目架构:
项目运行入口在Controller层的RunDemo。
入口函数内,会创建一个OpcUAClientRunner对象,并将IOC容器中的opcUAClientService传进去,并调用前者的run方法。
进入OpcUAClientRunner类的run方法后,又会调用同类createClient()方法,这是具体的创建连接的方法,在里面会创建安全证书保存路径、加载安全证书(使用到了KeyStoreLoader类)、寻找策略,最终返回连接client。
回到run()方法,利用该链接和刚刚传进来的opcUAClientService,调用后者的run()方法,进去后,调用业务层的代码。
因此如果需要对业务做出改变,只需要更改业务层的代码和类即可。
地址:UseMilo
修改OpcUAClientRunner类、OpcUAClientService接口里面的密码为我们设置的用户密码,使用用户名和密码认证。
在OpcUAClientService接口中修改服务器端口,没有更改的话,使用默认的即可。
在OpcUAClientService接口修改项目里的安全策略,选择KEPServerex6里面我们勾选的其中一个。
运行一次项目,生成证书文件,打开KEPServerEX6的OPCUA配置,选择受信任的客户端,信任我们刚刚生成的证书。
修改项目的业务代码,具体将读值方法的identifier属性修改成自己创建的tag标签名。
该类用于生成一个客户端访问的证书,提交给服务器,该类内容无需更改。我们只需要运行一遍代码之后生成证书,之后在KEPServerEX6中的OPCUA配置中信任客户端,即信任该证书即可。
这里的PASSWORD = password,是证书的私钥,我们不用管。
- class KeyStoreLoader {
-
- private static final Pattern IP_ADDR_PATTERN = Pattern.compile(
- "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
-
- private static final String CLIENT_ALIAS = "client-ai";
- private static final char[] PASSWORD = "password".toCharArray();
-
- private final Logger logger = LoggerFactory.getLogger(getClass());
-
- private X509Certificate[] clientCertificateChain;
- private X509Certificate clientCertificate;
- private KeyPair clientKeyPair;
-
- KeyStoreLoader load(Path baseDir) throws Exception {
- KeyStore keyStore = KeyStore.getInstance("PKCS12");
-
- Path serverKeyStore = baseDir.resolve("example-client.pfx");
-
- logger.info("Loading KeyStore at {}", serverKeyStore);
-
- if (!Files.exists(serverKeyStore)) {
- keyStore.load(null, PASSWORD);
-
- KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048);
-
- SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair)
- .setCommonName("Eclipse Milo Example Client")
- .setOrganization("digitalpetri")
- .setOrganizationalUnit("dev")
- .setLocalityName("Folsom")
- .setStateName("CA")
- .setCountryCode("US")
- .setApplicationUri("urn:eclipse:milo:examples:client")
- .addDnsName("localhost")
- .addIpAddress("127.0.0.1");
-
- // Get as many hostnames and IP addresses as we can listed in the certificate.
- for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) {
- if (IP_ADDR_PATTERN.matcher(hostname).matches()) {
- builder.addIpAddress(hostname);
- } else {
- builder.addDnsName(hostname);
- }
- }
-
- X509Certificate certificate = builder.build();
-
- keyStore.setKeyEntry(CLIENT_ALIAS, keyPair.getPrivate(), PASSWORD, new X509Certificate[]{certificate});
- try (OutputStream out = Files.newOutputStream(serverKeyStore)) {
- keyStore.store(out, PASSWORD);
- }
- } else {
- try (InputStream in = Files.newInputStream(serverKeyStore)) {
- keyStore.load(in, PASSWORD);
- }
- }
-
- Key clientPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD);
- if (clientPrivateKey instanceof PrivateKey) {
- clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);
-
- clientCertificateChain = Arrays.stream(keyStore.getCertificateChain(CLIENT_ALIAS))
- .map(X509Certificate.class::cast)
- .toArray(X509Certificate[]::new);
-
- PublicKey serverPublicKey = clientCertificate.getPublicKey();
- clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) clientPrivateKey);
- }
-
- return this;
- }
-
- X509Certificate getClientCertificate() {
- return clientCertificate;
- }
-
- public X509Certificate[] getClientCertificateChain() {
- return clientCertificateChain;
- }
-
- KeyPair getClientKeyPair() {
- return clientKeyPair;
- }
-
- }
如果你在跑了一次代码之后,修改了相应的内容,发现证书信任了同样连接不上,你可以尝试到你保存证书的目录删除,因为存在证书就不会再次生成证书进行覆盖。
C:\Users\用户名\AppData\Local\Temp\security(注意填充系统用户名)
在OpcUAClientRunner类中创建客户端的时候,需要传入客户端的配置,就需要设置具体的端口,
获取端口的时候,会利用给的url和端口号进去查找,查找的是milo项目内原本的安全策略项,一般有四个,是全部获取。我们提供的一个URL会和4个安全策略,生成4哥endpoint。
之后根据我们在前面<运行代码--2修改安全策略>做出的修改进行筛选,最后选取我们在代码中写入的安全策略,将该endpoint过滤出来(过滤方式有两种)。
假设你认识OPCUA协议,我们应该知道,协议的重点是节点和引用,它们共同组成地址空间。它们都会采用对象模型作为信息模型,在Java中,我们表现为一个具体的类。
也就是说我们的值存在节点里面,通过地址空间可以找到节点。所以在对节点进行操作的时候,我们需要标识一个节点,就通过两个属性,第一个是namespaceIndex,也就是地址空间索引,我们使用KEPServerEX6的话,默认是2,因此基本都填2。
NodeId(int namespaceIndex, String identifier)
indentifers是标识,它用来确定服务器器内具体的tag,由通道名.设备名.标签名构成。
运行一遍代码之后才生成证书,才能在KEPServerEX6中的OPCUA配置中信任客户端。
右击运行图标----OPCUA配置,受信任的客户端,点击列表中被红色叉标记的项,点击信任。
如果没有信任证书,就会报错:
- [org.eclipse.milo.opcua.stack.client.ClientChannelManager]-Channel bootstrap failed: An error occurred verifying security.
- UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
- at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.onError(UaTcpClientMessageHandler.java:716)
- at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decodeMessage(UaTcpClientMessageHandler.java:411)
- at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decode(UaTcpClientMessageHandler.java:392)
- at io.netty.handler.codec.ByteToMessageCodec$1.decode(ByteToMessageCodec.java:42)
- at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:387)
- at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245)
- at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103)
- at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292)
- at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:278)
- at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:962)
- at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
- at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528)
- at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:485)
- at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:399)
- at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:371)
- at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
- at java.lang.Thread.run(Thread.java:750)
- [com.milo.OpcUAClientRunner]-OPC UA客户端运行错误: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
- java.util.concurrent.ExecutionException: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
- at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
- at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908)
- at com.milo.OpcUAClientServiceImpl.run(OpcUAClientServiceImpl.java:25)
- at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:61)
- at com.controller.RunDemo.main(RunDemo.java:39)
- Caused by: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
- at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.onError(UaTcpClientMessageHandler.java:716)
- at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decodeMessage(UaTcpClientMessageHandler.java:411)
- at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decode(UaTcpClientMessageHandler.java:392)
- at io.netty.handler.codec.ByteToMessageCodec$1.decode(ByteToMessageCodec.java:42)
- at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:387)
- at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245)
- at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103)
- at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292)
- at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:278)
- at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:962)
- at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
- at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528)
- at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:485)
- at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:399)
- at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:371)
- at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
- at java.lang.Thread.run(Thread.java:750)
- [com.milo.OpcUAClientRunner]-连接OPC UA服务错误: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
- java.util.concurrent.ExecutionException: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
- at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
- at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908)
- at com.milo.OpcUAClientServiceImpl.run(OpcUAClientServiceImpl.java:25)
- at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:61)
- at com.controller.RunDemo.main(RunDemo.java:39)
- Caused by: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
- at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.onError(UaTcpClientMessageHandler.java:716)
- at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decodeMessage(UaTcpClientMessageHandler.java:411)
- at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decode(UaTcpClientMessageHandler.java:392)
- at io.netty.handler.codec.ByteToMessageCodec$1.decode(ByteToMessageCodec.java:42)
- at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:387)
- at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245)
- at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103)
- at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292)
- at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:278)
- at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:962)
- at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
- at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528)
- at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:485)
- at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:399)
- at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:371)
- at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
- at java.lang.Thread.run(Thread.java:750)
此外,在证书生成类中的,setApplicationUri中的值必须跟创建创建客户端createClient()的时候填入的setApplicationUri的值保持一致,因为创建的客户端连接,就是通过证书被服务器放行的。
如果不这么做就会导致报错误:
- java.util.concurrent.CompletionException: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
- at java.util.concurrent.CompletableFuture.encodeRelay(CompletableFuture.java:326)
- at java.util.concurrent.CompletableFuture.completeRelay(CompletableFuture.java:338)
- at java.util.concurrent.CompletableFuture.uniRelay(CompletableFuture.java:925)
- at java.util.concurrent.CompletableFuture$UniRelay.tryFire(CompletableFuture.java:913)
- at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
- at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
- at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.lambda$receiveResponse$16(UaTcpStackClient.java:367)
- at org.eclipse.milo.opcua.stack.core.util.ExecutionQueue$PollAndExecute.run(ExecutionQueue.java:107)
- at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
- at java.util.concurrent.FutureTask.run(FutureTask.java:266)
- at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
- at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
- at java.lang.Thread.run(Thread.java:750)
- Caused by: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
- ... 7 more
- [org.eclipse.milo.opcua.sdk.client.session.SessionFsm]-S(Creating)xE(CreateSessionFailureEvent) = S(Inactive)
- [com.milo.OpcUAClientRunner]-OPC UA客户端运行错误: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
- java.util.concurrent.ExecutionException: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
- at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
- at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908)
- at com.milo.OpcUAClientServiceImpl.run(OpcUAClientServiceImpl.java:25)
- at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:61)
- at com.controller.RunDemo.main(RunDemo.java:39)
- Caused by: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
- at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.lambda$receiveResponse$16(UaTcpStackClient.java:367)
- at org.eclipse.milo.opcua.stack.core.util.ExecutionQueue$PollAndExecute.run(ExecutionQueue.java:107)
- at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
- at java.util.concurrent.FutureTask.run(FutureTask.java:266)
- at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
- at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
- at java.lang.Thread.run(Thread.java:750)
- [com.milo.OpcUAClientRunner]-连接OPC UA服务错误: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
- java.util.concurrent.ExecutionException: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
- at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
- at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908)
- at com.milo.OpcUAClientServiceImpl.run(OpcUAClientServiceImpl.java:25)
- at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:61)
- at com.controller.RunDemo.main(RunDemo.java:39)
- Caused by: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
- at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.lambda$receiveResponse$16(UaTcpStackClient.java:367)
- at org.eclipse.milo.opcua.stack.core.util.ExecutionQueue$PollAndExecute.run(ExecutionQueue.java:107)
- at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
- at java.util.concurrent.FutureTask.run(FutureTask.java:266)
- at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
- at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
- at java.lang.Thread.run(Thread.java:750)
代码配置的安全策略和KEPServerEX6中服务器配置的安全策略不一致时,会报错:
请及时修改代码中的安全策略,或者修改服务器中的安全策略,并重新初始化服务器。
- java.util.concurrent.CompletionException: UaServiceFaultException: status=Bad_Shutdown, message=The operation was cancelled because the application is shutting down.
- at java.util.concurrent.CompletableFuture.encodeRelay(CompletableFuture.java:326)
- at java.util.concurrent.CompletableFuture.completeRelay(CompletableFuture.java:338)
- at java.util.concurrent.CompletableFuture.uniRelay(CompletableFuture.java:925)
- at java.util.concurrent.CompletableFuture$UniRelay.tryFire(CompletableFuture.java:913)
- at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
- at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
- at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.lambda$receiveResponse$16(UaTcpStackClient.java:367)
- at org.eclipse.milo.opcua.stack.core.util.ExecutionQueue$PollAndExecute.run(ExecutionQueue.java:107)
- at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
- at java.util.concurrent.FutureTask.run(FutureTask.java:266)
- at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
- at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
- at java.lang.Thread.run(Thread.java:750)
- Caused by: UaServiceFaultException: status=Bad_Shutdown, message=The operation was cancelled because the application is shutting down.
- ... 7 more
- [org.eclipse.milo.opcua.sdk.client.session.SessionFsm]-S(Creating) x E(CreateSessionFailureEvent) = S'(Inactive)
该问题可能性比较多。
本项目跑起来会用日志抛出两个一样的异常:org.eclipse.milo.opcua.stack.client.ClientChannelManager.connect:
第一个出现在:
- java.lang.Exception
- at org.eclipse.milo.opcua.stack.client.ClientChannelManager.connect(ClientChannelManager.java:67)
- at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.connect(UaTcpStackClient.java:127)
- at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.getEndpoints(UaTcpStackClient.java:577)
- at com.milo.OpcUAClientRunner.createClient(OpcUAClientRunner.java:88)
- at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:43)
- at com.controller.RunDemo.main(RunDemo.java:39)
第二个出现在:
- java.lang.Exception
- at org.eclipse.milo.opcua.stack.client.ClientChannelManager.connect(ClientChannelManager.java:67)
- at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.connect(UaTcpStackClient.java:127)
- at org.eclipse.milo.opcua.sdk.client.OpcUaClient.connect(OpcUaClient.java:312)
- at com.milo.OpcUAClientServiceImpl.run(OpcUAClientServiceImpl.java:25)
- at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:61)
- at com.controller.RunDemo.main(RunDemo.java:39)
这两个错误都不会影响我们进行连接、读取。
我的理解是,由客户端主动发起的连接关闭,两次都像是一种确认,确认服务器可达。第一次确定后获得服务器的安全策略,第二次确认后获得服务器的连接。
- 0PC UA客户端运行误: java,nio.channels,UnresolvedAddressException
- java.util.concurrent.ExecutionException Create breakpoint:java.nio.channels.UnresolvedAddressException
通过以下方式排查:
1、URL、安全策略、用户认证填写正确,在Client.connect().get()打断点,判断有没有成功生成Client。
2、打开Client属性,下滑到最后一个个找到config,依序打开,stackClientConfig---endpoint---查看endpointURl。
3、如果你看到的是域名,而不是ip,但是你在填写url却填入的是ip。这是因为主机连接内网之后,本地域名服务器刷新,无法解析域名。
4、我们只需要 用管理员身份 运行记事本,然后打开C:\windows\system32\drivers\etc的hosts文件,填入最后一行,格式为:IP地址 域名
5、注意中间有一个tab符。
6、测试成功。
已经实现订阅功能:
- private void subscribe(OpcUaClient client) throws Exception {
- AtomicInteger atomic = new AtomicInteger(1);
-
- //创建发布间隔1000ms的订阅对象
- client
- .getSubscriptionManager()
- .createSubscription(1000.0)
- .thenAccept(t -> {
- //节点1
- NodeId nodeId1 = new NodeId(2,"my.device.x1");
- ReadValueId readValueId1 = new ReadValueId(nodeId1, AttributeId.Value.uid(), null, null);
- //节点2
- NodeId nodeId2 = new NodeId(2,"my.device.x2");
- ReadValueId readValueId2 = new ReadValueId(nodeId2, AttributeId.Value.uid(), null, null);
-
- //创建监控的参数
- MonitoringParameters parameters = new MonitoringParameters(UInteger.valueOf(atomic.getAndIncrement()), 1000.0, null, UInteger.valueOf(10), true);
-
- //创建监控项请求
- //该请求最后用于创建订阅。
- MonitoredItemCreateRequest request1 = new MonitoredItemCreateRequest(readValueId1, MonitoringMode.Reporting, parameters);
- MonitoredItemCreateRequest request2 = new MonitoredItemCreateRequest(readValueId2, MonitoringMode.Reporting, parameters);
-
- List<MonitoredItemCreateRequest> requests = new ArrayList<>();
- requests.add(request1);
- requests.add(request2);
-
- //创建监控项,并且注册变量值改变时候的回调函数。
- t.createMonitoredItems(
- TimestampsToReturn.Both,
- requests,
- (item, id) -> item.setValueConsumer((it, val) -> {
- System.out.println("标识为" + it.getReadValueId().getNodeId()+"的项的值被更新为:"+ val.getValue().getValue());
- })
- );
- }).get();
-
- //持续订阅
- Thread.sleep(Long.MAX_VALUE);
- }
订阅功能参考文献:SpringBoot集成Milo库实现OPC UA客户端:连接、遍历节点、读取、写入、订阅与批量订阅-CSDN博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。