最近接了一个项目,需要访问工业的实时数据库,数据库的对外开放接口是OPCUA协议的,经过多方比对,发现github上milo的评星较高,尝试了一下,还比较方便好用,现在把使用过程中的坑和大家介绍一下,网上比较全的资料不多,下面是整个过程全部的资料:

本次采用KEPServerEX5模拟服务端,使用milo开发的程序作为客户端

一、搭建服务端,KEPServerEX5的安装省略掉,下面是配置过程
设置通道、设备、标签

设置访问的用户名和密码

设置通过opc-ua访问的节点

二、使用milo的框架,开发客户端访问opcua服务
1、在pom文件中追击以下依赖

<!--start milo-->
<dependency><groupId>org.eclipse.milo</groupId><artifactId>sdk-client</artifactId><version>0.2.4</version>
</dependency>
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk15on</artifactId><version>1.57</version>
</dependency>
<dependency><groupId>org.eclipse.milo</groupId><artifactId>sdk-server</artifactId><version>0.2.4</version>
</dependency>
<!--end milo-->

2、OPC UA协议对象接口

package com.jndj.platform.common.milo;import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;/*** @author yaohj* @date 2020/7/30* OPC UA协议对象接口*/
public interface OpcUAClientService {/*** OPC UA服务器地址和接口*/default String getEndpointUrl() {return "opc.tcp://127.0.0.1:49320";}/*** 过滤返回的server endpoint*/default Predicate<EndpointDescription> endpointFilter() {return e -> true;}/*** 连接服务器的安全策略* None、Basic128Rsa15、Basic256、Basic256Sha256、Aes128_Sha256_RsaOaep、Aes256_Sha256_RsaPss*/default SecurityPolicy getSecurityPolicy() {return SecurityPolicy.None;}/*** 提供身份验证*/default IdentityProvider getIdentityProvider() {return new AnonymousProvider();}/*** 实际操作服务、由实现类重写实现*/void run(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception;
}

3、OPC UA协议对象实体类

package com.jndj.platform.common.milo;import com.google.common.collect.ImmutableList;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.types.builtin.*;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.concurrent.CompletableFuture;@Service("OpcUAClientService")
public class OpcUAClientServiceImpl implements OpcUAClientService {/*** 覆盖接口的方法,建立和OPC UA的服务*/@Overridepublic void run(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception {// 同步建立连接client.connect().get();// 异步读取数据readTagData(client).thenAccept(values -> {DataValue nodeId_Tag1 = values.get(0);DataValue nodeId_Tag2 = values.get(1);System.out.println("#########Tag1=" + nodeId_Tag1.getValue().getValue());System.out.println("#########Tag2=" + nodeId_Tag2.getValue().getValue());future.complete(client);});}/*** 读取标签点的数据*/private CompletableFuture<List<DataValue>> readTagData(OpcUaClient client) {NodeId nodeId_Tag1 = new NodeId(2, "Channel1.Device1.Tag1");NodeId nodeId_Tag2 = new NodeId(2, "Channel1.Device1.Tag2");List<NodeId> nodeIds = ImmutableList.of(nodeId_Tag1, nodeId_Tag2);return client.readValues(0.0, TimestampsToReturn.Both, nodeIds);}
}

4、OPC UA协议运行对象

package com.jndj.platform.common.milo;import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig;
import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
import org.eclipse.milo.opcua.stack.client.UaTcpStackClient;
import org.eclipse.milo.opcua.stack.core.Stack;
import org.eclipse.milo.opcua.stack.core.types.builtin.LocalizedText;
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;@Service("OpcUAClientRunner")
public class OpcUAClientRunner {private final Logger logger = LoggerFactory.getLogger(getClass());private final CompletableFuture<OpcUaClient> future = new CompletableFuture<>();private final OpcUAClientService opcUAClientService;public OpcUAClientRunner(OpcUAClientService opcUAClientService) {this.opcUAClientService = opcUAClientService;}/*** OPC UA的运行入口程序*/public void run() {try {// 创建OPC UA客户端OpcUaClient opcUaClient = createClient();// future执行完毕后,异步判断状态future.whenCompleteAsync((c, ex) -> {if (ex != null) {logger.error("连接OPC UA服务错误: {}", ex.getMessage(), ex);}// 关闭OPC UA客户端try {opcUaClient.disconnect().get();Stack.releaseSharedResources();} catch (InterruptedException | ExecutionException e) {logger.error("OPC UA服务关闭错误: {}", e.getMessage(), e);}});try {// 获取OPC UA服务器的数据opcUAClientService.run(opcUaClient, future);future.get(5, TimeUnit.SECONDS);} catch (Throwable t) {logger.error("OPC UA客户端运行错误: {}", t.getMessage(), t);future.completeExceptionally(t);}} catch (Throwable t) {logger.error("OPC UA客户端创建错误: {}", t.getMessage(), t);future.completeExceptionally(t);}}/*** 创建OPC UA的服务连接对象*/private OpcUaClient createClient() throws Exception {Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");Files.createDirectories(securityTempDir);if (!Files.exists(securityTempDir)) {throw new Exception("不能够创建安全路径: " + securityTempDir);}KeyStoreLoader loader = new KeyStoreLoader().load(securityTempDir);// 获取OPC UA的服务器端节点EndpointDescription[] endpoints =UaTcpStackClient.getEndpoints(opcUAClientService.getEndpointUrl()).get();EndpointDescription endpoint = Arrays.stream(endpoints).filter(e -> e.getEndpointUrl().equals(opcUAClientService.getEndpointUrl())).findFirst().orElseThrow(() -> new Exception("没有节点返回"));// 设置OPC UA的配置信息OpcUaClientConfig config =OpcUaClientConfig.builder().setApplicationName(LocalizedText.english("OPC UA SCREEN")).setApplicationUri("urn:DATA-TRANSFER:OPC UA SCREEN").setCertificate(loader.getClientCertificate()).setKeyPair(loader.getClientKeyPair()).setEndpoint(endpoint).setIdentityProvider(new UsernameProvider("Administrator", "123456")).setRequestTimeout(uint(5000)).build();// 创建OPC UA客户端return new OpcUaClient(config);}
}

5、OPC UA访问证书类

package com.jndj.platform.common.milo;import org.eclipse.milo.opcua.sdk.server.util.HostnameUtil;
import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.*;
import java.security.cert.X509Certificate;
import java.util.regex.Pattern;class KeyStoreLoader {private final Logger logger = LoggerFactory.getLogger(getClass());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 X509Certificate clientCertificate;// 密钥对对象private KeyPair clientKeyPair;KeyStoreLoader load(Path baseDir) throws Exception {// 创建一个使用`PKCS12`加密标准的KeyStore。KeyStore在后面将作为读取和生成证书的对象。KeyStore keyStore = KeyStore.getInstance("PKCS12");// PKCS12的加密标准的文件后缀是.pfx,其中包含了公钥和私钥。// 而其他如.der等的格式只包含公钥,私钥在另外的文件中。Path serverKeyStore = baseDir.resolve("example-client.pfx");logger.info("Loading KeyStore at {}", serverKeyStore);// 如果文件不存在则创建.pfx证书文件。if (!Files.exists(serverKeyStore)) {keyStore.load(null, PASSWORD);// 用2048位的RAS算法。`SelfSignedCertificateGenerator`为Milo库的对象。KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048);// `SelfSignedCertificateBuilder`也是Milo库的对象,用来生成证书。// 中间所设置的证书属性可以自行修改。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 serverPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD);if (serverPrivateKey instanceof PrivateKey) {// 获取对应别名的证书对象。clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);// 获取公钥PublicKey serverPublicKey = clientCertificate.getPublicKey();// 创建Keypair对象。clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) serverPrivateKey);}return this;}// 返回证书X509Certificate getClientCertificate() {return clientCertificate;}// 返回密钥对KeyPair getClientKeyPair() {return clientKeyPair;}
}

6、业务service类

package com.jndj.platform.phase2.service.impl;import com.jndj.platform.common.milo.OpcUAClientRunner;
import com.jndj.platform.common.milo.OpcUAClientService;
import com.jndj.platform.phase2.service.Phase2Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** @author yaohj* @date 2020/7/22* 获取二期发电数据(三、四号机组)*/
@Service("phase2Service")
public class Phase2ServiceImpl implements Phase2Service {@Autowiredprivate OpcUAClientService opcUAClientService;/*** 获取二期发电数据(三、四号机组),保存到数据库中*/@Overridepublic void searchPhase2ElectricData() {new OpcUAClientRunner(opcUAClientService).run();}
}

7、业务Controller类、定时调度

package com.jndj.platform.phase2.controller;import com.jndj.platform.phase2.service.Phase2Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;import java.text.SimpleDateFormat;
import java.util.Date;/*** @author yaohj* @date 2020/7/22* 获取二期发电数据(三、四号机组)*/
@Controller
public class Phase2Controller {private static final Logger logger = LoggerFactory.getLogger(Phase2Controller.class);private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy:mm:dd HH:mm:ss");@Autowiredprivate Phase2Service phase2Service;/*** 获取二期发电数据(三、四号机组),保存到数据库中(x分钟调度一次)*/@Scheduled(initialDelay = 30000, fixedRate = 30000)public void searchGasData() {logger.info("####获取二期发电数据(三、四号机组) - 定时任务执行时间:"+ dateFormat.format(new Date()));phase2Service.searchPhase2ElectricData();}
}

8、运行结果、定时获取到opcua服务中的数据

OK,以上是所有的源代码,大家的问题基本能够解决,如果还有疑问,可一个给我发私信

使用java的milo框架访问OPCUA服务的方法相关推荐

  1. java怎么访问私有类_如何从Java类的外部访问类的私有方法?

    您可以使用java反射包访问类的私有方法. 步骤1-通过传递声明为私有的方法的方法名称来实例化java.lang.reflect包的Method类. 步骤2-通过将值true传递给setAccessi ...

  2. java接口允许ajax访问_服务允许AJAX请求,允许跨域请求

    当工作时间,因为需要JS 进行AJAX请求,这时候存在跨域问题,当出现这种情况时,有多种方案解决比如使用JSONP,也有一种简单的方式,就是在过滤器里面增加返回请求允许跨域head配置. 代码如下: ...

  3. 基于java(springboot框架)家政服务预约系统 开题报告

  4. java se 7web_JAX-WS ::从独立的Java 7 SE客户端调用Web服务的方法

    我正在尝试独立的JAX-WS Web服务,服务器和客户端(意思是,不在 Java EE容器内运行).显示独立服务器端的好SO帖子是 this one. 对于客户端,我发现了以下三种似乎有效的方法(使用 ...

  5. java jolt tuxedo_Java中使用Jolt访问Tuxedo服务 – Tomcat环境部署测试

    Java中使用Jolt访问Tuxedo服务 – Tomcat环境部署测试 Java中使用Jolt访问Tuxedo服务 – Tomcat环境部署测试 最近在学习基于Tuxedo的系统架构,网上讨论最多的 ...

  6. Android访问WCF服务(使用json实现参数传递)

    经过多日努力, 终于勉强弄明白了Android访问WCF服务的方法. 服务端实现 一, 实现服务. 操作契约 [csharp] view plaincopy [ServiceContract] pub ...

  7. Java之集合框架图及 Collection和Collections的区别及用法总结

    Java中Collection和Collections的区别: 1.Java集合框架图: 2.Collection接口: java.util.Collection是一个集合接口,其中定义了对集合对象有 ...

  8. 服务器返回的my为空,WCF REST服务:方法参数(对象)为空

    为什么我的WCF Rest服务方法的参数始终为空?....我确实访问了服务的方法,并且得到了wcf方法返回的字符串,但该参数保持为空.WCF REST服务:方法参数(对象)为空 经营合同: [Oper ...

  9. OPCUA标准java实现 Milo库

    Milo库 今天跟大家来介绍一下一个OPC UA协议的开源库,我们使用的现场设备为西门子的S7-1500 CPU,西门子的S7-1500在V2.1版本后就直接可以作为OPC UA的服务器来供其他客户端 ...

最新文章

  1. 雷军:年轻人入职半年内不要对战略和业务提意见,很多想法都不靠谱
  2. DF学数据结构系列——B树(B-树和B+树)介绍
  3. swoole学习(一)----linux安装swoole
  4. 1.24 Lambda表达式与匿名内部类的联系和区别
  5. Async/Await替代Promise的6个理由
  6. “中国智造”为System x提供创新源动力
  7. 计算机网络学习笔记(25. Cookie技术)
  8. C语言程序设计(第三版)何钦铭著 习题2-6
  9. base64 img图片按父div等比例显示
  10. Java Web九大内置对象及四大域对象
  11. 关于 MySQL bug 91418 一些看法
  12. 解决gateway转发websocket出现Max frame length of 65536 has been exceeded
  13. Java开发erp系统,高级面试题+解析
  14. 无线路由器常用的五种工作模式详细介绍
  15. 小公司一个人如何进行测试
  16. C3P Software 发布 Cast-Designer V7.7版本
  17. IT屌丝:SKYCC组合营销软件事件营销案例
  18. 三本计算机怎么调音乐,读三本音乐教材
  19. java命令 打 war包、解压war包
  20. Recent Learning Plan(近期计算机摸鱼计划)

热门文章

  1. createjs初学-关于Ticker
  2. 2021信创“大比武”正式启动!金山办公助力信创人才培养和生态成熟
  3. Android掌中游斗地主游戏源码完整版
  4. java中compliant是什么意思,compliant是什么意思中文翻译
  5. 坚果pro android版本,好用得不像安卓 | 坚果Pro系统深度体验
  6. 百度TV运营商随视传媒发布新广告平台AdMan
  7. 解决打包APK时候的报错:uses-sdk:minSdkVersion 22 cannot be smaller than version 23 declared in library
  8. java中isprime_java:19:找不到符号 符号:方法isPrime(int) 位置:类ziji_9
  9. 新版标准日本语高级_第14课
  10. 大数据Flink最强手册