import com.sun.org.apache.xpath.internal.operations.Bool;
import lombok.extern.slf4j.Slf4j;
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.DiscoveryClient;
import org.eclipse.milo.opcua.stack.core.types.builtin.*;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
@Slf4j
@Component
public class OpcUaUtils {
private static String endPointUrl;
private static String username;
private static String password;
@Value("${relay_opc.endPointUrl}")
public void setEndPointUrl(String endPointUrl) {
this.endPointUrl = endPointUrl;
}
@Value("${relay_opc.username}")
public void setUsername(String username) {
this.username = username;
}
@Value("${relay_opc.password}")
public void setPassword(String password) {
this.password = password;
}
public static OpcUaClient createClient(String endPointUrl, String username, String password) 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);//创建OpcUA的访问证书类对象
// 获取OPC UA的服务器端节点
List<EndpointDescription> listEndPoints = DiscoveryClient.getEndpoints(endPointUrl).get();
EndpointDescription endpoint = listEndPoints.get(0);
// 设置OPC UA的配置信息
OpcUaClientConfig config =
OpcUaClientConfig.builder()
.setApplicationName(LocalizedText.english("Jisco OpcUa Client"))
.setApplicationUri("urn:jicso:milo:opcua:client")//放入url
.setCertificate(loader.getClientCertificate())//需要传入一个数字证书作为形参,我们用KeyStoreLoader类创建了
.setKeyPair(loader.getClientKeyPair())//传入密匙对
.setEndpoint(endpoint)//EndpointDescription对象,就是设置刚刚选择的节点就可以了
//使用匿名登录方式
.setIdentityProvider(new UsernameProvider(username, password))//使用用户名认证的访问验证方式
.setRequestTimeout(uint(5000))//设置请求超时时间,单位为毫秒。
.build();
// 创建OPC UA客户端
return OpcUaClient.create(config);
}
/**
* 读取节点数据
*
* @param client OPC UA客户端
* @throws Exception
*/
public static DataValue readNode(OpcUaClient client, int namespaceIndex,
String identifier) throws Exception {
//节点
NodeId nodeId = new NodeId(namespaceIndex, identifier);
//读取节点数据
return client.readValue(0.0, TimestampsToReturn.Neither, nodeId).get();
}
/**
* 写入节点数据
*
* @param client
* @throws Exception
*/
public static StatusCode writeNodeValue(OpcUaClient client, int namespaceIndex,
String identifier, Variant variant) throws Exception {
//节点
NodeId nodeId = new NodeId(namespaceIndex, identifier);
//创建数据对象,此处的数据对象一定要定义类型,不然会出现类型错误,导致无法写入
DataValue nowValue = new DataValue(variant, null, null);
long begin = System.currentTimeMillis();
//写入节点数据
return client.writeValue(nodeId, nowValue).get();
}
public static int writeNodeValues(OpcUaClient client, List<NodeId> nodes, List<DataValue> values) throws Exception {
if (nodes == null || values == null) {
throw new NullPointerException("nodes or values is null");
}
if (nodes.size() != values.size()) {
throw new IllegalArgumentException("nodeIds.size() != values.size()");
}
int count = nodes.size();
CompletableFuture<List<StatusCode>> f = client.writeValues(nodes, values);
List<StatusCode> statusCodes = f.get();
for (int i = 0; i < statusCodes.size(); i++) {
if (statusCodes.get(i).isBad()) {
log.error("write '{}' to nodeId={} failed",
values.get(i) != null ? values.get(i).getValue().getValue().toString() : "null",
nodes.get(i).getIdentifier().toString());
count--;
}
}
return count;
}
public static int writeNodeValues(List<NodeId> nodes, List<DataValue> values) throws Exception {
if (nodes == null || values == null) {
throw new NullPointerException("nodes or values is null");
}
if (nodes.size() != values.size()) {
throw new IllegalArgumentException("nodeIds.size() != values.size()");
}
//1.获取opc客户端
OpcUaClient client = OpcUaUtils.createClient(endPointUrl, username, password);
client.connect().get();
int count = nodes.size();
CompletableFuture<List<StatusCode>> f = client.writeValues(nodes, values);
List<StatusCode> statusCodes = f.get();
for (int i = 0; i < statusCodes.size(); i++) {
if (statusCodes.get(i).isBad()) {
log.error("write '{}' to nodeId={} failed",
values.get(i) != null ? values.get(i).getValue().getValue().toString() : "null",
nodes.get(i).getIdentifier().toString());
count--;
}
}
return count;
}
public static void main(String[] args) throws Exception {
String endPointUrl = "opc.tcp://127.0.0.1:49320";
OpcUaClient client = createClient(endPointUrl, "admin", "admin");
client.connect().get();
//StatusCode statusCode = writeNodeValue(client,2,"test03.test03.String",new Variant("abc"));
//System.out.println(statusCode.isGood());
//DataValue dataValue = readNode(client,2,"test03.test03.String");
//System.out.println(dataValue.getValue().getValue().toString());
//批量写入点位数据
List<NodeId> nodes = new ArrayList<>();
List<DataValue> values = new ArrayList<>();
nodes.add(new NodeId(2, "AGvisual.stockInalertdevice.alert_time_1"));
nodes.add(new NodeId(2, "AGvisual.stockInalertdevice.coil_no_1"));
nodes.add(new NodeId(2, "AGvisual.stockInalertdevice.ocr_text_1"));
nodes.add(new NodeId(2, "AGvisual.stockInalertdevice.saddle_no_1"));
nodes.add(new NodeId(2, "AGvisual.stockInalertdevice.status_1"));
nodes.add(new NodeId(2, "AGvisual.stockInalertdevice.track_no_1"));
// nodes.add(new NodeId(2, "AGvisual.deviatealertdevice.alert_time"));
// nodes.add(new NodeId(2, "AGvisual.deviatealertdevice.position"));
// nodes.add(new NodeId(2, "AGvisual.deviatealertdevice.center_offset"));
// values.add(new DataValue(new Variant(new Boolean(true)), null, null));
// values.add(new DataValue(new Variant(String.valueOf("9")), null, null));
// values.add(new DataValue(new Variant(String.valueOf("9")), null, null));
// values.add(new DataValue(new Variant(String.valueOf("9")), null, null));
values.add(new DataValue(new Variant(String.valueOf("20240106151601")), null, null));
values.add(new DataValue(new Variant(String.valueOf("1025B2106")), null, null));
values.add(new DataValue(new Variant(String.valueOf("1025B2106")), null, null));
values.add(new DataValue(new Variant(Short.valueOf("1")), null, null));
values.add(new DataValue(new Variant(String.valueOf("1025B2106")), null, null));
values.add(new DataValue(new Variant(Short.valueOf("1")), null, null));
// values.add(new DataValue(new Variant(Float.parseFloat("111")), null, null));
// values.add(new DataValue(new Variant(Float.parseFloat("1025B2106")), null, null));
// values.add(new DataValue(new Variant(Float.parseFloat("11")), null, null));
// values.add(new DataValue(new Variant(Float.parseFloat("22")), null, null));
// values.add(new DataValue(new Variant(Float.parseFloat("33")), null, null));
int ln = writeNodeValues(client, nodes, values);
System.out.println("ln=" + ln);
// for(int i=0;i<nodes.size();i++){
// NodeId nodeId = nodes.get(i);
// Variant variant = values.get(i).getValue();
//
// writeNodeValue(client,2,nodeId.getIdentifier().toString(),variant);
// }
//批量读取点位
// List<NodeId> nodes = new ArrayList<>();
// nodes.add(new NodeId(2, "AGcaralarm.s_device.alarm.la_error1"));
// nodes.add(new NodeId(2, "AGcaralarm.s_device.alarm.la_error10"));
// List<DataValue> values = client.readValues(0.0,TimestampsToReturn.Neither,nodes).get();
// for(DataValue dataValue : values){
// System.out.println(dataValue.getValue().getValue().toString());
// }
// writeNodeValue(client,2,"AGcaralarm.alarmdevice.la_error_1-1",new Variant(false));
}
}
创建证书对象
```java
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.Arrays;
import java.util.regex.Pattern;
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");
SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair)
.setCommonName("Jisco OpcUa Client")
.setOrganization("Jisco")
.setOrganizationalUnit("dev")
.setLocalityName("Jisco")
.setStateName("CN")
.setCountryCode("ZH")
.setApplicationUri("urn:jicso:milo:opcua: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;
}
}