一、环境准备
首先需要,安装KEPServerEX 6 Configuration和UaExpert
以下是安装包地址:
-
KEPServerEX 6 地址
链接:https://pan.baidu.com/s/1BIJvrJBApqsOwqQUC0Oofw
提取码:hz0j
安装KEPServerEX的时候,可以不设置管理员密码,如图所示,跳过设置密码
KEPServer Ex6 UaExpert 地址
链接:https://pan.baidu.com/s/1wJPnI-EiRJ8rKrLNtuAFzw
提取码:1hvw
二、配置KEPServerEx
1、 安装好之后,在任务栏右击配置KEPServerEx
1
2
2、设置用户名密码
3
3、设置OPCUA
4
4、根据自己实际情况设置OPCUA,我这里的安全测试设置的最低。
5
5、选择项目,右击选择属性
image.png
6、选择opcua将服务启动
image.png
7、新建一个通道,用于后续测试使用
image.png
8、设置通道类型为Simulator
image.png
9、设置一个名称
image.png
10、其他步骤都为默认即可,最后点击弯沉即可
image.png
11、然后在test通道上添加设备,如图所示
image.png
12、后面默认即可,最后点击完成
image.png
13、设置属性值
image.png
14、设置名称,地址和默认值(该配置由于java读取或设置节点值)
image.png
15、在test通道上继续新建设备,步骤与device一样
image.png
16、设置静态标记,地址为RANDOM,默认值为short
image.png
17、结果如图所示
image.png
三、配置UaExpert
1、添加服务
image.png
2、设置地址
image.png
image.png
出现如下消息表示连接成功
image.png
3、在Address space找打刚刚设置的通道和设备信息
image.png
4、将绿色的name拖进中间显示窗口(右侧的Attributes的NodeId为java需要的地址信息)
image.png
四、java代码编写
1、pom依赖如下
<dependency>
<groupId>org.eclipse.milo</groupId>
<artifactId>sdk-client</artifactId>
<version>0.6.9</version>
</dependency>
<dependency>
<groupId>org.eclipse.milo</groupId>
<artifactId>sdk-server</artifactId>
<version>0.6.9</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
2、业务代码如下。后续自己封装
package com.opcua.opcuatest.serve;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
import org.eclipse.milo.opcua.stack.core.AttributeId;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.*;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import org.eclipse.milo.opcua.stack.core.types.enumerated.MonitoringMode;
import org.eclipse.milo.opcua.stack.core.types.enumerated.TimestampsToReturn;
import org.eclipse.milo.opcua.stack.core.types.structured.MonitoredItemCreateRequest;
import org.eclipse.milo.opcua.stack.core.types.structured.MonitoringParameters;
import org.eclipse.milo.opcua.stack.core.types.structured.ReadValueId;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
*
* </p>
*
* @author wsh
* @date 2023/4/27 21:35
*/
public class OpcUaTest {
//opc ua服务端地址
private final static String endPointUrl = "opc.tcp://127.0.0.1:49320";
public static void main(String[] args) {
try {
//创建OPC UA客户端
OpcUaClient opcUaClient = createClient();
//开启连接
opcUaClient.connect().get();
// 订阅消息
subscribe(opcUaClient);
// 写入
// writeValue(opcUaClient);
// 读取
// readValue(opcUaClient);
// 关闭连接
opcUaClient.disconnect().get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 创建OPC UA客户端
*
* @return
* @throws Exception
*/
private static OpcUaClient createClient() throws Exception {
Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
Files.createDirectories(securityTempDir);
if (!Files.exists(securityTempDir)) {
throw new Exception("unable to create security dir: " + securityTempDir);
}
return OpcUaClient.create(endPointUrl,
endpoints ->
endpoints.stream()
.filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
.findFirst(),
configBuilder ->
configBuilder
.setApplicationName(LocalizedText.english("")) // huazh-01
.setApplicationUri("") // ns=2:s=huazh-01.device1.data-huazh
//访问方式 new AnonymousProvider()
.setIdentityProvider(new UsernameProvider("ua", "12345678901112"))
.setRequestTimeout(UInteger.valueOf(5000))
.build()
);
}
private static void subscribe(OpcUaClient client) throws Exception {
//创建发布间隔1000ms的订阅对象
client.getSubscriptionManager()
.createSubscription(1000.0)
.thenAccept(t -> {
//节点ns=2;s=test.device2.test2
NodeId nodeId = new NodeId(2, "test.device2.test2");
ReadValueId readValueId = new ReadValueId(nodeId, AttributeId.Value.uid(), null, null);
//创建监控的参数
MonitoringParameters parameters = new MonitoringParameters(UInteger.valueOf(1), 1000.0, null, UInteger.valueOf(10), true);
//创建监控项请求
//该请求最后用于创建订阅。
MonitoredItemCreateRequest request = new MonitoredItemCreateRequest(readValueId, MonitoringMode.Reporting, parameters);
List<MonitoredItemCreateRequest> requests = new ArrayList<>();
requests.add(request);
//创建监控项,并且注册变量值改变时候的回调函数。
t.createMonitoredItems(
TimestampsToReturn.Both,
requests,
(item, id) -> item.setValueConsumer((it, val) -> {
System.out.println("=====订阅nodeid====== :" + it.getReadValueId().getNodeId());
System.out.println("=====订阅value===== :" + val.getValue().getValue());
})
);
}).get();
//持续订阅
Thread.sleep(Long.MAX_VALUE);
}
public static void readValue(OpcUaClient client) {
try {
NodeId nodeId = new NodeId(2, "test.device.name");
DataValue value = client.readValue(0.0, TimestampsToReturn.Both, nodeId).get();
System.out.println("=====读取ua1====:" + value.getValue().getValue());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void writeValue(OpcUaClient client) {
try {
//创建变量节点 test.device2.test2
NodeId nodeId = new NodeId(2, "test.device2.test2");
//uda3 boolean
Short value = 11;
//创建Variant对象和DataValue对象
Variant v = new Variant(value);
DataValue dataValue = new DataValue(v, null, null);
StatusCode statusCode = client.writeValue(nodeId, dataValue).get();
System.out.println(statusCode);
System.out.println("=====写入ua1====:" + statusCode.isGood());
} catch (Exception e) {
e.printStackTrace();
}
}
}