Java代码实现opc ua历史数据读取
·OPC UA(Open Platform Communications Unified Architecture)·是一种工业通信协议,旨在提供安全可靠的工业数据交换。随着工业4.0和物联网技术的发展,OPC UA成为了连接各种设备和系统的重要桥梁。本文将介绍如何使用Java编程语言通过·OPC UA·协议从服务器读取历史数据。
引入依赖
首先在SpringBoot
项目的pom
文件中引入milo
依赖
<dependency>
<groupId>org.eclipse.milo</groupId>
<artifactId>sdk-client</artifactId>
<version>0.6.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
示例代码
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.UaException;
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.*;
import java.util.ArrayList;
import java.util.List;
import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
import static org.eclipse.milo.opcua.stack.core.util.ConversionUtil.l;
public class HistoryReadExampleProsys {
public static void main(String[] args) throws Exception {
OpcUaClient client=create("opc.tcp://10.16.91.47:12685");
run(client);
}
public static OpcUaClient create(String endPointUrl) throws UaException {
return OpcUaClient.create(endPointUrl);
}
public static void run(OpcUaClient client) throws Exception {
client.connect().get();
HistoryReadDetails historyReadDetails = new ReadRawModifiedDetails(
false,
DateTime.MIN_VALUE,
DateTime.now(),
uint(0),
true
);
HistoryReadValueId historyReadValueId = new HistoryReadValueId(
new NodeId(2, "FAB,数据.全局煤机位置架号"), //指定要读取的节点点位
null,
QualifiedName.NULL_VALUE,
ByteString.NULL_VALUE
);
List<HistoryReadValueId> nodesToRead = new ArrayList<>();
nodesToRead.add(historyReadValueId);
HistoryReadResponse historyReadResponse = client.historyRead(
historyReadDetails,
TimestampsToReturn.Both,
false,
nodesToRead
).get();
HistoryReadResult[] historyReadResults = historyReadResponse.getResults();
if (historyReadResults != null) {
HistoryReadResult historyReadResult = historyReadResults[0];
StatusCode statusCode = historyReadResult.getStatusCode();
if (statusCode.isGood()) {
HistoryData historyData = (HistoryData) historyReadResult.getHistoryData().decode(
client.getStaticSerializationContext()
);
List<DataValue> dataValues = l(historyData.getDataValues());
dataValues.forEach(v -> System.out.println("value=" + v));
} else {
System.out.println("History read failed: " + statusCode);
}
}
}
}
- 注意点位历史数据读取功能,必须opc ua 服务器支持历史存储和读取,代码才生效
- 本代码只是单类的测试代码,需要根据自己的需求进行改造
- 设置
HistoryReadValueId
对象中的nodeId
为你要读取点位节点即可!
代码解读
下面是对您提供的Java代码的逐行解读,这段代码展示了如何使用某个OPC UA
客户端库从指定地址的历史数据存储中读取历史数据。请注意,代码中使用的类和方法名可能根据具体的OPC UA
库实现有所变化。
public class HistoryReadExampleProsys {
定义了一个名为 HistoryReadExampleProsys
的公共类。
public static void main(String[] args) throws Exception {
定义了主函数 main
,这是Java程序的入口点。该方法声明可能会抛出异常。
OpcUaClient client = create("opc.tcp://10.16.91.47:12685");
调用静态方法 create
创建一个OPC UA客户端实例,连接到指定的服务器地址 opc.tcp://10.16.91.47:12685
。
run(client);
调用静态方法 run
,传入刚刚创建的客户端实例,开始执行主要逻辑。
public static OpcUaClient create(String endPointUrl) throws UaException {
定义静态方法 create
,接收一个字符串参数 endPointUrl
,表示OPC UA服务器的端点URL,返回一个 OpcUaClient
实例。此方法声明可能会抛出 UaException
异常。
return OpcUaClient.create(endPointUrl);
使用传入的端点URL创建并返回一个新的 OpcUaClient
实例。
public static void run(OpcUaClient client) throws Exception {
定义静态方法 run
,接收一个 OpcUaClient
类型的参数 client
,执行主要的操作逻辑。此方法声明可能会抛出异常。
client.connect().get();
尝试连接到OPC UA服务器。.get()
方法等待异步操作完成。
HistoryReadDetails historyReadDetails = new ReadRawModifiedDetails(
false,
DateTime.MIN_VALUE,
DateTime.now(),
uint(0),
true
);
创建一个 HistoryReadDetails
对象,用于指定历史数据读取的详细信息。这里使用 ReadRawModifiedDetails
构造器初始化对象,设置参数分别为:
false
: 不请求修改后的值。DateTime.MIN_VALUE
: 起始时间为最早可能的时间。DateTime.now()
: 结束时间为当前时间。uint(0)
: 返回的最大值数量无限制。true
: 返回所有可用的数据。
HistoryReadValueId historyReadValueId = new HistoryReadValueId(
new NodeId(3, "Counter"),
null,
QualifiedName.NULL_VALUE,
ByteString.NULL_VALUE
);
创建一个 HistoryReadValueId
对象,用于指定要读取历史数据的节点ID。这里指定了节点ID为 NodeId(3, "Counter")
,其余参数设为默认值。
List<HistoryReadValueId> nodesToRead = new ArrayList<>();
nodesToRead.add(historyReadValueId);
创建一个 List
存储要读取历史数据的节点ID列表,并添加之前创建的 historyReadValueId
。
HistoryReadResponse historyReadResponse = client.historyRead(
historyReadDetails,
TimestampsToReturn.Both,
false,
nodesToRead
).get();
调用客户端的 historyRead
方法发起历史数据读取请求,参数分别为:
historyReadDetails
: 历史数据读取的详细信息。TimestampsToReturn.Both
: 请求同时返回源时间和服务器时间戳。false
: 不请求连续读取。nodesToRead
: 要读取的节点列表。
.get()
方法等待异步操作完成。
HistoryReadResult[] historyReadResults = historyReadResponse.getResults();
从响应中获取读取结果数组。
if (historyReadResults != null) {
检查读取结果是否为空。
HistoryReadResult historyReadResult = historyReadResults[0];
StatusCode statusCode = historyReadResult.getStatusCode();
获取第一个读取结果及其状态码。
if (statusCode.isGood()) {
检查状态码是否表示成功。
HistoryData historyData = (HistoryData) historyReadResult.getHistoryData().decode(
client.getStaticSerializationContext()
);
如果成功,解码历史数据。
List<DataValue> dataValues = l(historyData.getDataValues());
获取解码后的数据值列表。这里的 l
方法可能是一个自定义的方法,用来转换或包装数据值列表。
dataValues.forEach(v -> System.out.println("value=" + v));
遍历数据值列表,并打印每个数据值。
} else {
System.out.println("History read failed: " + statusCode);
}
如果状态码表示失败,打印错误信息。