这篇文章介绍如何使用opc ua的方式,访问opc数据。
1、引入依赖
<!-- milo连接opc -->
<dependency>
<groupId>org.eclipse.milo</groupId>
<artifactId>sdk-client</artifactId>
<version>0.6.8</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.70</version>
</dependency>
<dependency>
<groupId>org.eclipse.milo</groupId>
<artifactId>sdk-server</artifactId>
<version>0.6.8</version>
</dependency>
<dependency>
<groupId>org.eclipse.milo</groupId>
<artifactId>dictionary-reader</artifactId>
<version>0.6.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.milo</groupId>
<artifactId>dictionary-manager</artifactId>
<version>0.6.0</version>
</dependency>
View Code
2、初始化opc ua客户端
@Component
public class ClientGen {
//加载加密类型
static {
Security.addProvider(new BouncyCastleProvider());
}
private final Logger log = LoggerFactory.getLogger(getClass());
// milo用来连接opc ua的client
public static OpcUaClient opcUaClient;
@Autowired
private OpcUaConfig opcUaConfig;
/**
* 创建opc ua客户端(在项目启动的时候执行该方法)
*
*/
@PostConstruct
public void createClient_() throws UaException {
String endPoint = opcUaConfig.getEndpointUrl();
opcUaClient = OpcUaClient.create(
endPoint,
endpointDescriptions -> {
final List<EndpointDescription> collect = endpointDescriptions.stream().collect(Collectors.toList());
final Optional<EndpointDescription> first = endpointDescriptions
.stream()
.findFirst();
System.out.println(first.get().getSecurityPolicyUri());
return Optional.of(collect.get(0));
},
configBuilder ->
configBuilder
.setApplicationName(LocalizedText.english("opc-ua client"))
.setApplicationUri(endPoint)
// .setIdentityProvider(new UsernameProvider(username, password))
.setIdentityProvider(new AnonymousProvider())
.setRequestTimeout(uint(5000))
.build()
);
log.info("创建客户端:{} 成功!", opcUaClient);
}
/**
* 创建opc ua客户端(在项目启动的时候执行该方法)
*
*/
public void createClient(){
try {
Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
Files.createDirectories(securityTempDir);
if (!Files.exists(securityTempDir)) {
throw new Exception("没有创建安全目录: " + securityTempDir);
}
log.info("安全目录: {}", securityTempDir.toAbsolutePath());
//加载秘钥
KeyStoreLoader loader = new KeyStoreLoader().load(securityTempDir);
//安全策略 None、Basic256、Basic128Rsa15、Basic256Sha256
SecurityPolicy securityPolicy = SecurityPolicy.None;
List<EndpointDescription> endpoints;
try {
endpoints = DiscoveryClient.getEndpoints(opcUaConfig.getEndpointUrl()).get();
} catch (Throwable ex) {
String discoveryUrl = opcUaConfig.getEndpointUrl();
if (!discoveryUrl.endsWith("/")) {
discoveryUrl += "/";
}
discoveryUrl += "discovery";
log.info("开始连接 URL: {}", discoveryUrl);
endpoints = DiscoveryClient.getEndpoints(discoveryUrl).get();
}
EndpointDescription endpoint = endpoints.stream()
.filter(e -> e.getEndpointUrl().equals(opcUaConfig.getEndpointUrl()))
.findFirst().orElseThrow(() -> new Exception("没有节点返回"));
//.filter(e -> e.getSecurityPolicyUri().equals(securityPolicy.getUri()))
//.filter(opcUaConfig.endpointFilter())
//.findFirst()
//.orElseThrow(() -> new Exception("没有连接上端点"));
log.info("使用端点: {} [{}/{}]", endpoint.getEndpointUrl(), securityPolicy, endpoint.getSecurityMode());
OpcUaClientConfig config = OpcUaClientConfig.builder()
.setApplicationName(LocalizedText.english("eclipse milo opc-ua client"))
.setApplicationUri("urn:eclipse:milo:examples:client")
.setCertificate(loader.getClientCertificate()) // 证书
.setKeyPair(loader.getClientKeyPair())
.setEndpoint(endpoint)
//根据匿名验证和第三个用户名验证方式设置传入对象 AnonymousProvider(匿名方式)UsernameProvider(账户密码)
.setIdentityProvider(new AnonymousProvider())
.setRequestTimeout(uint(100000000))
.build();
opcUaClient = OpcUaClient.create(config);
log.info("创建客户端:{} 成功!", opcUaClient);
} catch (Exception e) {
log.error("创建客户端失败" + e.getMessage());
}
}
}
View Code
3、批量采集opc实时数据
/**
* 采集一标段和二标段的数据
*/
private List<DbBlockDto> gatherSectionOneData(List<NodeId> nodeIds) throws ExecutionException, InterruptedException {
List<DbBlockDto> dtoList = new ArrayList<>();
// 获取opc ua客户端
OpcUaClient client = ClientGen.opcUaClient;
log.info("client is: {}", client);
// 链接opc ua
client.connect().get();
// 批量采集数据
final CompletableFuture<List<DataValue>> data = client.readValues(0d, TimestampsToReturn.Neither, nodeIds);
List<DataValue> dataValues = data.get();
if (dataValues == null) {
return dtoList;
}
// 封装数据
for (int i = 0; i < dataValues.size(); i++) {
DbBlockDto dbBlockDto = new DbBlockDto();
DataValue value = dataValues.get(i);
dbBlockDto.setName(nodeIds.get(i).getIdentifier().toString().substring(2));
// 校验数据
if(value.getStatusCode() != null){
if (value.getStatusCode().isGood()) {
String plcValue = value.getValue().getValue().toString();
dbBlockDto.setValue(plcValue);
}
}
dtoList.add(dbBlockDto);
}
return dtoList;
}
View Code
注:1、读取数据时,需要将业务变量名称封装成 “t|业务字段”的形式
// 将二标段DB块的变量名称,拼接成t|xxx的格式
blocks.parallelStream().forEach(n -> n.setName("t|" + n.getName()));
List<NodeId> nodeIdList = new ArrayList<>();
for(DbBlock dbBlock : blocks){
NodeId nodeId = new NodeId(1, dbBlock.getName());
nodeIdList.add(nodeId);
}
2、本机的host文件需要配置为opc服务器的服务地址
public String getEndpointUrl() {
return "opc.tcp://XmcWinCCServer:4862";
}
源码:https://gitee.com/caesarthegreat/opc.git