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

这篇具有很好参考价值的文章主要介绍了【OPCUA】使用Java开源项目milo连接KEPServerEX6服务器并读取值。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

准备工作:

开发环境: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位),后续代码使用用户认证需要用到。

java opc milo 检测标记状态,协议相关,java,硬件工程

java opc milo 检测标记状态,协议相关,java,硬件工程

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

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

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

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

java opc milo 检测标记状态,协议相关,java,硬件工程

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

打开KEPServerEX6界面

java opc milo 检测标记状态,协议相关,java,硬件工程

 通道类型选择Simulator

java opc milo 检测标记状态,协议相关,java,硬件工程

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

java opc milo 检测标记状态,协议相关,java,硬件工程

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

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

java opc milo 检测标记状态,协议相关,java,硬件工程

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

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

java opc milo 检测标记状态,协议相关,java,硬件工程

填入标记名称,地址

java opc milo 检测标记状态,协议相关,java,硬件工程

java opc milo 检测标记状态,协议相关,java,硬件工程

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

java opc milo 检测标记状态,协议相关,java,硬件工程

java opc milo 检测标记状态,协议相关,java,硬件工程

值的Quality应该显示为良好。

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

java opc milo 检测标记状态,协议相关,java,硬件工程

java opc milo 检测标记状态,协议相关,java,硬件工程

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

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

5、打开项目的匿名登录

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

java opc milo 检测标记状态,协议相关,java,硬件工程

6、补充

使用KEPServerEX6创建的通道我们选择了Simulator,作为服务器的通道。他的默认的地址空间为2,即项目中读取时填入的NodeID的namespaceindex为2。我们通过下面的操作也可以看得到。

我们当然也可以右击项目的连接性,再新建一个通道,通道类型选择OPCUA Client,之后依旧使用英文通道名、设备名,不过需要注意的是:

java opc milo 检测标记状态,协议相关,java,硬件工程

创建OPCUA Client这个通道作为的是一个客户端,因此需要写入连接的服务器的url,我们连接到就是另一个通道,所以使用,opc.tcp://localhost:49320。安全策略也需要跟服务器的保持一致。

java opc milo 检测标记状态,协议相关,java,硬件工程

同时还需要输入我们在前面第一节新建的用户名账号和密码,进行用户认证,让服务器放行。

java opc milo 检测标记状态,协议相关,java,硬件工程

之后下一步、完成。

之后对该通道新建设备,输入英文设备名,之后一直下一步,直到可以导入项。

java opc milo 检测标记状态,协议相关,java,硬件工程

点击导入,就会自动使用刚刚新建通道的时候填入的rul、安全策略、用户名认证进行连接,之后读取里面的值,你可以具体选择一些项进行导入。之后我们就可以在新建的设备上看到他们。注意看,默认的ns确实是2,具体的indentifers名组成为:通道名.设备名.标签名。

java opc milo 检测标记状态,协议相关,java,硬件工程

这时候就会生成一个客户端,需要驱动进行运行,保持客户端的活性,这是软件官方的付费功能,只能免费运行两小时,之后就会被取消链接。

运行项目

项目架构:

        项目运行入口在Controller层的RunDemo。

        入口函数内,会创建一个OpcUAClientRunner对象,并将IOC容器中的opcUAClientService传进去,并调用前者的run方法。

        进入OpcUAClientRunner类的run方法后,又会调用同类createClient()方法,这是具体的创建连接的方法,在里面会创建安全证书保存路径、加载安全证书(使用到了KeyStoreLoader类)、寻找策略,最终返回连接client。

        回到run()方法,利用该链接和刚刚传进来的opcUAClientService,调用后者的run()方法,进去后,调用业务层的代码。

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

1、clone项目

地址:UseMilo

2、修改用户

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

java opc milo 检测标记状态,协议相关,java,硬件工程

java opc milo 检测标记状态,协议相关,java,硬件工程

3、修改端口URL

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

java opc milo 检测标记状态,协议相关,java,硬件工程

4、修改安全策略

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

java opc milo 检测标记状态,协议相关,java,硬件工程

5、运行生成证书

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

java opc milo 检测标记状态,协议相关,java,硬件工程

6、信任客户端

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

java opc milo 检测标记状态,协议相关,java,硬件工程

7、直接运行RunDemo。

项目代码解读:

1、KeyStoreLoader类

        该类用于生成一个客户端访问的证书,提交给服务器,该类内容无需更改。我们只需要运行一遍代码之后生成证书,之后在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(注意填充系统用户名)

2、Endpoints端口

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

java opc milo 检测标记状态,协议相关,java,硬件工程

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

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

java opc milo 检测标记状态,协议相关,java,硬件工程

java opc milo 检测标记状态,协议相关,java,硬件工程

3、地址空间AdressSpace、节点Node

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

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

NodeId(int namespaceIndex, String identifier)

java opc milo 检测标记状态,协议相关,java,硬件工程

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

可能出现的错误总结:

1、证书没有被信任

运行一遍代码之后才生成证书,才能在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)
2、ApplicationURL不匹配

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

java opc milo 检测标记状态,协议相关,java,硬件工程

java opc milo 检测标记状态,协议相关,java,硬件工程

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

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)
3、获取不到端点值

代码配置的安全策略和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)
4、连接上了读取不到值、读空值null

该问题可能性比较多。

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

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

第一个出现在:

java opc milo 检测标记状态,协议相关,java,硬件工程

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 opc milo 检测标记状态,协议相关,java,硬件工程

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)

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

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

6、获取不到端点,地址解析失败
0PC UA客户端运行误: java,nio.channels,UnresolvedAddressException
java.util.concurrent.ExecutionException Create breakpoint:java.nio.channels.UnresolvedAddressException

通过以下方式排查:

1、URL、安全策略、用户认证填写正确,在Client.connect().get()打断点,判断有没有成功生成Client。

java opc milo 检测标记状态,协议相关,java,硬件工程

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博客文章来源地址https://www.toymoban.com/news/detail-764897.html

到了这里,关于【OPCUA】使用Java开源项目milo连接KEPServerEX6服务器并读取值的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 通过Milo实现的OPC UA客户端连接并订阅Prosys OPC UA Simulation Server模拟服务器

    前面我们搭建了一个本地的 PLC 仿真环境,并通过 KEPServerEX6 读取 PLC 上的数据,最后还使用 UAExpert 作为 OPC 客户端完成从 KEPServerEX6 这个OPC服务器的数据读取与订阅功能:SpringBoot集成Milo库实现OPC UA客户端:连接、遍历节点、读取、写入、订阅与批量订阅。 注意,如果实际工

    2024年02月16日
    浏览(35)
  • 【学习笔记之opcua】使用Python获取opcua数据

    Python与OPC UA的应用 示例代码 将代码放入spyder中运行后,出现下面这个错误 没有‘opcua’,那我们就下载 pip install opcua 之后出现下面这个错误 问问题大不,安装语句写错了 正经安装语句是 !pip install opcua 输出

    2024年02月12日
    浏览(25)
  • S7-1500 通过 TIA15, S7-PLCSIM Advanced V4.0 仿真PLC 与 KEPServerEX 6 建立server 建立连接

    S7-1500 通过 TIA15,S7-PLCSIM Advanced V4.0 仿真PLC 与KEPServerEX 6 建立server 建立连接 软件硬件环境 : PLC , 使用 S7-PLCSIMAdvanced V4.0 仿真器 客户端访问: KEPServerEX 6.5 作为 客户端 读取 PLC 变量 步骤1:建立S7-1500 仿真环境,如下图 打开S7-PLCSIM Advanced V4.0 软件 切换开关到虚拟网卡模式,

    2024年02月05日
    浏览(38)
  • IDEA项目实践——创建Java项目以及创建Maven项目案例、使用数据库连接池创建项目简介

    IDEA上面书写wordcount的Scala文件具体操作 IDEA创建项目的操作步骤以及在虚拟机里面创建Scala的项目简单介绍 目录 系列文章目录 前言 一 准备工作 1.1 安装Maven 1.1.1 Maven安装配置步骤 1.1.2 解压相关的软件包 1.1.3 Maven 配置环境变量 1.1.4 配置Maven的私服 1.2 创建一个本地的MySQL数据

    2024年02月04日
    浏览(44)
  • Java远程连接本地开源分布式搜索引擎ElasticSearch

    简单几步,结合Cpolar内网穿透工具实现Java远程连接操作本地Elasticsearch。 什么是elasticsearch?一个开源的分布式搜索引擎,具备非常多强大功能,可以用来实现搜索、日志统计、分析、系统监控等功能,可以帮助我们从海量数据中快速找到需要的内容。 Cpolar内网穿透提供了更高

    2024年02月05日
    浏览(36)
  • 智慧化工地SaaS平台源码,PC端+APP端+智慧数据可视化大屏端,源码完全开源不封装,自主研发,支持二开,项目使用,微服务+Java++vue+mysql

    智慧工地管理平台充分运用数字化技术,聚焦施工现场岗位一线,依托物联网、互联网、AI等技术,围绕施工现场管理的人、机、料、法、环五大维度,以及施工过程管理的进度、质量、安全三大体系为基础应用,实现全面高效的工程管理需求,满足工地多角色、多视角的有

    2024年02月11日
    浏览(38)
  • 模仿淘宝购物系统的Java Web前端项目(开源项目)

    提示:此项目仅作为本博主的学习笔记记录,不作为商品售卖,资源往下翻看源码获取 提示:这里可以添加本文要记录的大概内容: 本项目要求完成Java Web的开发环境准备,以及项目开发框架的搭建 Web开发环境准备,包括eclipse、MySQL、tomcat Web项目框架搭建,涉及jsp、servle

    2024年02月11日
    浏览(37)
  • Java开源项目mall学习笔记(1)——项目初始化

            该笔记是记录学习开源项目mall过程的文档笔记,完全原创,转载请声明。同时也对开源项目的作者表示感谢! mall: 🔥 mall项目是一套基于 SpringBoot + Vue + uni-app 实现的电商系统,包括前台商城项目及后台管理系统,采用Docker容器化部署。前台商城系统包含首页门户

    2024年02月12日
    浏览(33)
  • GitHub上热门的Java开源项目

    1 JavaGuide https://github.com/Snailclimb/JavaGuide Star 26396  一份Java学习指南,涵盖大部分Java程序员所需要掌握的核心知识 2 DoraemonKit https://github.com/didi/DoraemonKit Star 4826 简称 \\\"DoKit\\\",中文名哆啦A梦,意味着能够像哆啦A梦一样提供给他的主人各种各样的工具,一款功能齐全的客户端(

    2023年04月19日
    浏览(40)
  • 【开源】基于JAVA的企业项目合同信息系统

    基于JAVA+Vue+SpringBoot+MySQL的企业项目合同信息系统,包含了合同审批模块、合同签订模块、合同预定模块和合同数据可视化模块,还包含系统自带的用户管理、部门管理、角色管理、菜单管理、日志管理、数据字典管理、文件管理、图表展示等基础模块,企业项目合同信息系统

    2024年02月03日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包