日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用java的milo框架访问OPCUA服务的方法

發布時間:2023/12/14 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用java的milo框架访问OPCUA服务的方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近接了一個項目,需要訪問工業的實時數據庫,數據庫的對外開放接口是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服务的方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。