当前位置:   article > 正文

【OPCUA】使用Java开源项目milo连接KEPServerEX6服务器并读取值_eclipse milo

eclipse milo

准备工作:

开发环境: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组件库,分为三个大部分:

  • milo-examples:写了很多可运行类,介绍具体如何调用本项目的接口。分成客户端和服务器两部分。
  • opc-ua-sdk:OPCUA的软件开发工具包(对外可被调用。
    • sdk-client可以用来模拟服务器,我们服务器使用了KEPServerEX6。
    • sdk-server可以用来模拟客户端,我们用的大多数类都是这个包内的。
  • opc-ua-stack:是项目的底层支持,里面定义了很多通道、节点、数据类型、认证方式、错误类型等

KEPServerEX6服务器配置:

1、添加新用户

安装完成后,找到运行图标,右击打开设置---用户管理器---在Administrators下添加新用户,

记下账户名、密码(14位),后续代码使用用户认证需要用到。

2、OPC UA配置安全策略、URL

回到桌面任务栏,继续右击运行图标,打开OPC UA配置---服务器端点---双击黑色的服务器端点

本地测试时,网络适配器选择仅限本地主机。

访问地址(使用默认的就好),和安全策略(推荐像下图配置)都会具体在代码中体现。

3、新建通道、设备、标记

打开KEPServerEX6界面

 通道类型选择Simulator

自由设置通道名字、设备名字,但注意使用英文,否则可能出现连接上了读取不到tag值的问题。

之后一直点击下一步即可。

在创立出来的通道(你设置的名字)上,右击选择新建设备。

之后一直点击下一步即可。

单击新建的设备,在空白界面右击选择新建标记。

填入标记名称,地址

4、新建客户端尝试连接服务器,看看是否成功。

值的Quality应该显示为良好。

可以右击具体的标签项,选择Synchronous Write进行修改值内容。

需要注意的是,使用自己KEPServerEX6的客户端连接服务器,可能也需要进行客户端信任。

右击运行图标----OPCUA配置,受信任的客户端,点击列表中被红色叉标记的项,点击信任。

5、打开项目的匿名登录

回到KEPServerEX6软件的主界面,右击项目,选择属性。

6、补充

使用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()方法,进去后,调用业务层的代码。

        因此如果需要对业务做出改变,只需要更改业务层的代码和类即可。

1、clone项目

地址:UseMilo

2、修改用户

        修改OpcUAClientRunner类、OpcUAClientService接口里面的密码为我们设置的用户密码,使用用户名和密码认证。

3、修改端口URL

在OpcUAClientService接口中修改服务器端口,没有更改的话,使用默认的即可。

4、修改安全策略

在OpcUAClientService接口修改项目里的安全策略,选择KEPServerex6里面我们勾选的其中一个。

5、运行生成证书

        运行一次项目,生成证书文件,打开KEPServerEX6的OPCUA配置,选择受信任的客户端,信任我们刚刚生成的证书。

6、信任客户端

修改项目的业务代码,具体将读值方法的identifier属性修改成自己创建的tag标签名。

7、直接运行RunDemo。

项目代码解读:

1、KeyStoreLoader类

        该类用于生成一个客户端访问的证书,提交给服务器,该类内容无需更改。我们只需要运行一遍代码之后生成证书,之后在KEPServerEX6中的OPCUA配置中信任客户端,即信任该证书即可。

这里的PASSWORD = password,是证书的私钥,我们不用管。

  1. class KeyStoreLoader {
  2. private static final Pattern IP_ADDR_PATTERN = Pattern.compile(
  3. "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
  4. private static final String CLIENT_ALIAS = "client-ai";
  5. private static final char[] PASSWORD = "password".toCharArray();
  6. private final Logger logger = LoggerFactory.getLogger(getClass());
  7. private X509Certificate[] clientCertificateChain;
  8. private X509Certificate clientCertificate;
  9. private KeyPair clientKeyPair;
  10. KeyStoreLoader load(Path baseDir) throws Exception {
  11. KeyStore keyStore = KeyStore.getInstance("PKCS12");
  12. Path serverKeyStore = baseDir.resolve("example-client.pfx");
  13. logger.info("Loading KeyStore at {}", serverKeyStore);
  14. if (!Files.exists(serverKeyStore)) {
  15. keyStore.load(null, PASSWORD);
  16. KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048);
  17. SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair)
  18. .setCommonName("Eclipse Milo Example Client")
  19. .setOrganization("digitalpetri")
  20. .setOrganizationalUnit("dev")
  21. .setLocalityName("Folsom")
  22. .setStateName("CA")
  23. .setCountryCode("US")
  24. .setApplicationUri("urn:eclipse:milo:examples:client")
  25. .addDnsName("localhost")
  26. .addIpAddress("127.0.0.1");
  27. // Get as many hostnames and IP addresses as we can listed in the certificate.
  28. for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) {
  29. if (IP_ADDR_PATTERN.matcher(hostname).matches()) {
  30. builder.addIpAddress(hostname);
  31. } else {
  32. builder.addDnsName(hostname);
  33. }
  34. }
  35. X509Certificate certificate = builder.build();
  36. keyStore.setKeyEntry(CLIENT_ALIAS, keyPair.getPrivate(), PASSWORD, new X509Certificate[]{certificate});
  37. try (OutputStream out = Files.newOutputStream(serverKeyStore)) {
  38. keyStore.store(out, PASSWORD);
  39. }
  40. } else {
  41. try (InputStream in = Files.newInputStream(serverKeyStore)) {
  42. keyStore.load(in, PASSWORD);
  43. }
  44. }
  45. Key clientPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD);
  46. if (clientPrivateKey instanceof PrivateKey) {
  47. clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);
  48. clientCertificateChain = Arrays.stream(keyStore.getCertificateChain(CLIENT_ALIAS))
  49. .map(X509Certificate.class::cast)
  50. .toArray(X509Certificate[]::new);
  51. PublicKey serverPublicKey = clientCertificate.getPublicKey();
  52. clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) clientPrivateKey);
  53. }
  54. return this;
  55. }
  56. X509Certificate getClientCertificate() {
  57. return clientCertificate;
  58. }
  59. public X509Certificate[] getClientCertificateChain() {
  60. return clientCertificateChain;
  61. }
  62. KeyPair getClientKeyPair() {
  63. return clientKeyPair;
  64. }
  65. }

        如果你在跑了一次代码之后,修改了相应的内容,发现证书信任了同样连接不上,你可以尝试到你保存证书的目录删除,因为存在证书就不会再次生成证书进行覆盖。

        C:\Users\用户名\AppData\Local\Temp\security(注意填充系统用户名)

2、Endpoints端口

在OpcUAClientRunner类中创建客户端的时候,需要传入客户端的配置,就需要设置具体的端口,

        获取端口的时候,会利用给的url和端口号进去查找,查找的是milo项目内原本的安全策略项,一般有四个,是全部获取。我们提供的一个URL会和4个安全策略,生成4哥endpoint。

        之后根据我们在前面<运行代码--2修改安全策略>做出的修改进行筛选,最后选取我们在代码中写入的安全策略,将该endpoint过滤出来(过滤方式有两种)。

3、地址空间AdressSpace、节点Node

        假设你认识OPCUA协议,我们应该知道,协议的重点是节点和引用,它们共同组成地址空间。它们都会采用对象模型作为信息模型,在Java中,我们表现为一个具体的类。

        也就是说我们的值存在节点里面,通过地址空间可以找到节点。所以在对节点进行操作的时候,我们需要标识一个节点,就通过两个属性,第一个是namespaceIndex,也就是地址空间索引,我们使用KEPServerEX6的话,默认是2,因此基本都填2。

NodeId(int namespaceIndex, String identifier)

         indentifers是标识,它用来确定服务器器内具体的tag,由通道名.设备名.标签名构成。

可能出现的错误总结:

1、证书没有被信任

运行一遍代码之后才生成证书,才能在KEPServerEX6中的OPCUA配置中信任客户端。

右击运行图标----OPCUA配置,受信任的客户端,点击列表中被红色叉标记的项,点击信任。

如果没有信任证书,就会报错:

  1. [org.eclipse.milo.opcua.stack.client.ClientChannelManager]-Channel bootstrap failed: An error occurred verifying security.
  2. UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
  3. at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.onError(UaTcpClientMessageHandler.java:716)
  4. at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decodeMessage(UaTcpClientMessageHandler.java:411)
  5. at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decode(UaTcpClientMessageHandler.java:392)
  6. at io.netty.handler.codec.ByteToMessageCodec$1.decode(ByteToMessageCodec.java:42)
  7. at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:387)
  8. at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245)
  9. at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103)
  10. at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292)
  11. at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:278)
  12. at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:962)
  13. at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
  14. at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528)
  15. at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:485)
  16. at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:399)
  17. at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:371)
  18. at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
  19. at java.lang.Thread.run(Thread.java:750)
  20. [com.milo.OpcUAClientRunner]-OPC UA客户端运行错误: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
  21. java.util.concurrent.ExecutionException: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
  22. at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
  23. at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908)
  24. at com.milo.OpcUAClientServiceImpl.run(OpcUAClientServiceImpl.java:25)
  25. at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:61)
  26. at com.controller.RunDemo.main(RunDemo.java:39)
  27. Caused by: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
  28. at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.onError(UaTcpClientMessageHandler.java:716)
  29. at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decodeMessage(UaTcpClientMessageHandler.java:411)
  30. at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decode(UaTcpClientMessageHandler.java:392)
  31. at io.netty.handler.codec.ByteToMessageCodec$1.decode(ByteToMessageCodec.java:42)
  32. at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:387)
  33. at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245)
  34. at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103)
  35. at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292)
  36. at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:278)
  37. at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:962)
  38. at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
  39. at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528)
  40. at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:485)
  41. at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:399)
  42. at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:371)
  43. at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
  44. at java.lang.Thread.run(Thread.java:750)
  45. [com.milo.OpcUAClientRunner]-连接OPC UA服务错误: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
  46. java.util.concurrent.ExecutionException: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
  47. at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
  48. at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908)
  49. at com.milo.OpcUAClientServiceImpl.run(OpcUAClientServiceImpl.java:25)
  50. at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:61)
  51. at com.controller.RunDemo.main(RunDemo.java:39)
  52. Caused by: UaException: status=Bad_SecurityChecksFailed, message=An error occurred verifying security.
  53. at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.onError(UaTcpClientMessageHandler.java:716)
  54. at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decodeMessage(UaTcpClientMessageHandler.java:411)
  55. at org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler.decode(UaTcpClientMessageHandler.java:392)
  56. at io.netty.handler.codec.ByteToMessageCodec$1.decode(ByteToMessageCodec.java:42)
  57. at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:387)
  58. at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245)
  59. at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103)
  60. at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292)
  61. at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:278)
  62. at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:962)
  63. at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
  64. at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528)
  65. at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:485)
  66. at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:399)
  67. at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:371)
  68. at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
  69. at java.lang.Thread.run(Thread.java:750)
2、ApplicationURL不匹配

此外,在证书生成类中的,setApplicationUri中的值必须跟创建创建客户端createClient()的时候填入的setApplicationUri的值保持一致,因为创建的客户端连接,就是通过证书被服务器放行的。

如果不这么做就会导致报错误:

  1. java.util.concurrent.CompletionException: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
  2. at java.util.concurrent.CompletableFuture.encodeRelay(CompletableFuture.java:326)
  3. at java.util.concurrent.CompletableFuture.completeRelay(CompletableFuture.java:338)
  4. at java.util.concurrent.CompletableFuture.uniRelay(CompletableFuture.java:925)
  5. at java.util.concurrent.CompletableFuture$UniRelay.tryFire(CompletableFuture.java:913)
  6. at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
  7. at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
  8. at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.lambda$receiveResponse$16(UaTcpStackClient.java:367)
  9. at org.eclipse.milo.opcua.stack.core.util.ExecutionQueue$PollAndExecute.run(ExecutionQueue.java:107)
  10. at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
  11. at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  12. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  13. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  14. at java.lang.Thread.run(Thread.java:750)
  15. Caused by: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
  16. ... 7 more
  17. [org.eclipse.milo.opcua.sdk.client.session.SessionFsm]-S(Creating)xE(CreateSessionFailureEvent) = S(Inactive)
  18. [com.milo.OpcUAClientRunner]-OPC UA客户端运行错误: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
  19. java.util.concurrent.ExecutionException: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
  20. at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
  21. at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908)
  22. at com.milo.OpcUAClientServiceImpl.run(OpcUAClientServiceImpl.java:25)
  23. at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:61)
  24. at com.controller.RunDemo.main(RunDemo.java:39)
  25. Caused by: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
  26. at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.lambda$receiveResponse$16(UaTcpStackClient.java:367)
  27. at org.eclipse.milo.opcua.stack.core.util.ExecutionQueue$PollAndExecute.run(ExecutionQueue.java:107)
  28. at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
  29. at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  30. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  31. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  32. at java.lang.Thread.run(Thread.java:750)
  33. [com.milo.OpcUAClientRunner]-连接OPC UA服务错误: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
  34. java.util.concurrent.ExecutionException: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
  35. at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
  36. at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908)
  37. at com.milo.OpcUAClientServiceImpl.run(OpcUAClientServiceImpl.java:25)
  38. at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:61)
  39. at com.controller.RunDemo.main(RunDemo.java:39)
  40. Caused by: UaServiceFaultException: status=Bad_CertificateUriInvalid, message=The URI specified in the ApplicationDescription does not match the URI in the Certificate.
  41. at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.lambda$receiveResponse$16(UaTcpStackClient.java:367)
  42. at org.eclipse.milo.opcua.stack.core.util.ExecutionQueue$PollAndExecute.run(ExecutionQueue.java:107)
  43. at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
  44. at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  45. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  46. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  47. at java.lang.Thread.run(Thread.java:750)
3、获取不到端点值

代码配置的安全策略和KEPServerEX6中服务器配置的安全策略不一致时,会报错:

请及时修改代码中的安全策略,或者修改服务器中的安全策略,并重新初始化服务器。

  1. java.util.concurrent.CompletionException: UaServiceFaultException: status=Bad_Shutdown, message=The operation was cancelled because the application is shutting down.
  2. at java.util.concurrent.CompletableFuture.encodeRelay(CompletableFuture.java:326)
  3. at java.util.concurrent.CompletableFuture.completeRelay(CompletableFuture.java:338)
  4. at java.util.concurrent.CompletableFuture.uniRelay(CompletableFuture.java:925)
  5. at java.util.concurrent.CompletableFuture$UniRelay.tryFire(CompletableFuture.java:913)
  6. at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:488)
  7. at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1990)
  8. at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.lambda$receiveResponse$16(UaTcpStackClient.java:367)
  9. at org.eclipse.milo.opcua.stack.core.util.ExecutionQueue$PollAndExecute.run(ExecutionQueue.java:107)
  10. at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
  11. at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  12. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  13. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  14. at java.lang.Thread.run(Thread.java:750)
  15. Caused by: UaServiceFaultException: status=Bad_Shutdown, message=The operation was cancelled because the application is shutting down.
  16. ... 7 more
  17. [org.eclipse.milo.opcua.sdk.client.session.SessionFsm]-S(Creating) x E(CreateSessionFailureEvent) = S'(Inactive)
4、连接上了读取不到值、读空值null

该问题可能性比较多。

  • 可能是因为安全策略不匹配,但是服务器允许“无”,即匿名登陆,导致连接的上,但是没有权限获取得到值。
  • 可能是因为地址空间索引ns填错,如果没有进行特殊的修改,服务器中默认的ns为2。
  • 可能是因为节点的identifier标识使用了中文,安装KEPServerEX6的时候,可以让我们选择简体中文,但是连接的时候,设备的标识使用了中文,却连不上。本人因为这个问题调了2天的Bug。猜测是我这个版本的KEPServerEX6内核只能支持英文。
  • 或许更直接一点,可能是因为节点的identifier节点填错了
5、忽略channel...错误

本项目跑起来会用日志抛出两个一样的异常:org.eclipse.milo.opcua.stack.client.ClientChannelManager.connect:

第一个出现在:

  1. java.lang.Exception
  2. at org.eclipse.milo.opcua.stack.client.ClientChannelManager.connect(ClientChannelManager.java:67)
  3. at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.connect(UaTcpStackClient.java:127)
  4. at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.getEndpoints(UaTcpStackClient.java:577)
  5. at com.milo.OpcUAClientRunner.createClient(OpcUAClientRunner.java:88)
  6. at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:43)
  7. at com.controller.RunDemo.main(RunDemo.java:39)

第二个出现在:

  1. java.lang.Exception
  2. at org.eclipse.milo.opcua.stack.client.ClientChannelManager.connect(ClientChannelManager.java:67)
  3. at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.connect(UaTcpStackClient.java:127)
  4. at org.eclipse.milo.opcua.sdk.client.OpcUaClient.connect(OpcUaClient.java:312)
  5. at com.milo.OpcUAClientServiceImpl.run(OpcUAClientServiceImpl.java:25)
  6. at com.milo.OpcUAClientRunner.run(OpcUAClientRunner.java:61)
  7. at com.controller.RunDemo.main(RunDemo.java:39)

这两个错误都不会影响我们进行连接、读取。

我的理解是,由客户端主动发起的连接关闭,两次都像是一种确认,确认服务器可达。第一次确定后获得服务器的安全策略,第二次确认后获得服务器的连接。

6、获取不到端点,地址解析失败
  1. 0PC UA客户端运行误: java,nio.channels,UnresolvedAddressException
  2. 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、测试成功。

更新订阅功能:

已经实现订阅功能:

  1. private void subscribe(OpcUaClient client) throws Exception {
  2. AtomicInteger atomic = new AtomicInteger(1);
  3. //创建发布间隔1000ms的订阅对象
  4. client
  5. .getSubscriptionManager()
  6. .createSubscription(1000.0)
  7. .thenAccept(t -> {
  8. //节点1
  9. NodeId nodeId1 = new NodeId(2,"my.device.x1");
  10. ReadValueId readValueId1 = new ReadValueId(nodeId1, AttributeId.Value.uid(), null, null);
  11. //节点2
  12. NodeId nodeId2 = new NodeId(2,"my.device.x2");
  13. ReadValueId readValueId2 = new ReadValueId(nodeId2, AttributeId.Value.uid(), null, null);
  14. //创建监控的参数
  15. MonitoringParameters parameters = new MonitoringParameters(UInteger.valueOf(atomic.getAndIncrement()), 1000.0, null, UInteger.valueOf(10), true);
  16. //创建监控项请求
  17. //该请求最后用于创建订阅。
  18. MonitoredItemCreateRequest request1 = new MonitoredItemCreateRequest(readValueId1, MonitoringMode.Reporting, parameters);
  19. MonitoredItemCreateRequest request2 = new MonitoredItemCreateRequest(readValueId2, MonitoringMode.Reporting, parameters);
  20. List<MonitoredItemCreateRequest> requests = new ArrayList<>();
  21. requests.add(request1);
  22. requests.add(request2);
  23. //创建监控项,并且注册变量值改变时候的回调函数。
  24. t.createMonitoredItems(
  25. TimestampsToReturn.Both,
  26. requests,
  27. (item, id) -> item.setValueConsumer((it, val) -> {
  28. System.out.println("标识为" + it.getReadValueId().getNodeId()+"的项的值被更新为:"+ val.getValue().getValue());
  29. })
  30. );
  31. }).get();
  32. //持续订阅
  33. Thread.sleep(Long.MAX_VALUE);
  34. }

订阅功能参考文献:SpringBoot集成Milo库实现OPC UA客户端:连接、遍历节点、读取、写入、订阅与批量订阅-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/555979
推荐阅读
相关标签
  

闽ICP备14008679号