遍历OPCUA节点
1.使用OPCUA,获取PLC数据
问题:如果是结构体,数组发现不能够使用符号访问,只能用数字访问

为了解决这个问题,通过代码获取所有的节点数据,然后构建到map里面
简介访问数据

package plc.gy;
import cn.hutool.core.util.StrUtil;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode;
import org.eclipse.milo.opcua.stack.core.Identifiers;
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.BrowseDirection;
import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseDescription;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseResult;
import org.eclipse.milo.opcua.stack.core.types.structured.ReferenceDescription;
import java.util.*;
import java.util.concurrent.ExecutionException;
import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
public class OpcUaNodeMapper {
private static final String REQUIRED_KEYWORD = "服务器";
public static void main(String[] args) {
String endpointUrl = "opc.tcp://192.168.10.10:4840"; // OPC UA服务器地址
try {
OpcUaClient client = OpcUaClient.create(
endpointUrl,
endpoints -> endpoints.stream()
.filter(e -> e.getSecurityPolicyUri().equals("http://opcfoundation.org/UA/SecurityPolicy#None"))
.findFirst(),
configBuilder -> configBuilder
.setApplicationName(LocalizedText.english("OPC UA Mapper"))
.setApplicationUri("urn:eclipse:milo:examples:client")
.setRequestTimeout(uint(5000))
.build()
);
client.connect().get();
System.out.println("已连接到OPC UA服务器: " + endpointUrl);
Map<String, NodeId> nodeMap = new LinkedHashMap<>();
browseAndPrint(client, Identifiers.RootFolder, "", nodeMap);
client.disconnect().get();
System.out.println("已断开与服务器的连接");
} catch (Exception e) {
System.err.println("通信失败: " + e.getMessage());
e.printStackTrace();
}
}
private static void browseAndPrint(OpcUaClient client, NodeId nodeId, String path, Map<String, NodeId> nodeMap)
throws ExecutionException, InterruptedException, UaException {
BrowseDescription browse = new BrowseDescription(
nodeId,
BrowseDirection.Forward,
Identifiers.References,
true,
uint(NodeClass.Object.getValue() | NodeClass.Variable.getValue()),
uint(0x3f)
);
BrowseResult result = client.browse(browse).get();
ReferenceDescription[] refs = result.getReferences();
if (refs == null) return;
for (ReferenceDescription ref : refs) {
NodeId childId = ref.getNodeId().toNodeId(client.getNamespaceTable()).orElse(null);
if (childId == null) continue;
String browseName = ref.getBrowseName().getName();
String currentPath = path.isEmpty() ? browseName : path + "." + browseName;
NodeClass nodeClass = ref.getNodeClass();
// 1. 区分大小写
boolean hasServer = StrUtil.contains(currentPath, "服务器");
nodeMap.put(currentPath, childId);
String nodeType = (nodeClass == NodeClass.Variable) ? "变量节点" : "对象节点";
System.out.println("映射: " + currentPath + " → " + childId + "(" + nodeType + ")");
// 如果是变量节点,输出基础类型和数据类型
if (nodeClass == NodeClass.Variable) {
UaVariableNode varNode = client.getAddressSpace().getVariableNode(childId);
NodeId dataTypeId = varNode.getDataType();
String dataTypeStr = dataTypeId != null ? dataTypeId.toParseableString() : "未知";
String dataTypeName = client.getAddressSpace()
.getNode(dataTypeId)
.getBrowseName()
.getName();
System.out.println(" 基础类型: " + currentPath + ", 数据类型: " + dataTypeName);
}
// 递归浏览子节点
browseAndPrint(client, childId, currentPath, nodeMap);
}
}
}

优化1
package plc.gy;
import cn.hutool.core.util.StrUtil;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.nodes.UaVariableNode;
import org.eclipse.milo.opcua.stack.core.Identifiers;
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.BrowseDirection;
import org.eclipse.milo.opcua.stack.core.types.enumerated.NodeClass;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseDescription;
import org.eclipse.milo.opcua.stack.core.types.structured.BrowseResult;
import org.eclipse.milo.opcua.stack.core.types.structured.ReferenceDescription;
import java.util.*;
import java.util.concurrent.ExecutionException;
import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
public class OpcUaNodeMapper {
private static final String REQUIRED_KEYWORD = "服务器";
public static void main(String[] args) {
String endpointUrl = "opc.tcp://192.168.10.10:4840"; // OPC UA服务器地址
try {
OpcUaClient client = OpcUaClient.create(
endpointUrl,
endpoints -> endpoints.stream()
.filter(e -> e.getSecurityPolicyUri().equals("http://opcfoundation.org/UA/SecurityPolicy#None"))
.findFirst(),
configBuilder -> configBuilder
.setApplicationName(LocalizedText.english("OPC UA Mapper"))
.setApplicationUri("urn:eclipse:milo:examples:client")
.setRequestTimeout(uint(5000))
.build()
);
client.connect().get();
System.out.println("已连接到OPC UA服务器: " + endpointUrl);
Map<String, NodeId> nodeMap = new LinkedHashMap<>();
browseAndPrint(client, Identifiers.RootFolder, "", nodeMap);
client.disconnect().get();
System.out.println("已断开与服务器的连接");
} catch (Exception e) {
System.err.println("通信失败: " + e.getMessage());
e.printStackTrace();
}
}
private static void browseAndPrint(OpcUaClient client, NodeId nodeId, String path, Map<String, NodeId> nodeMap)
throws ExecutionException, InterruptedException, UaException {
BrowseDescription browse = new BrowseDescription(
nodeId,
BrowseDirection.Forward,
Identifiers.References,
true,
uint(NodeClass.Object.getValue() | NodeClass.Variable.getValue()),
uint(0x3f)
);
BrowseResult result = client.browse(browse).get();
ReferenceDescription[] refs = result.getReferences();
if (refs == null) return;
for (ReferenceDescription ref : refs) {
NodeId childId = ref.getNodeId().toNodeId(client.getNamespaceTable()).orElse(null);
if (childId == null) continue;
String browseName = ref.getBrowseName().getName();
String currentPath = path.isEmpty() ? browseName : path + "." + browseName;
NodeClass nodeClass = ref.getNodeClass();
// 1. 区分大小写
boolean hasServer = StrUtil.contains(currentPath, "服务器");
nodeMap.put(currentPath, childId);
String nodeType = (nodeClass == NodeClass.Variable) ? "变量节点" : "对象节点";
System.out.println("映射: " + currentPath + " → " + childId + "(" + nodeType + ")");
// 如果是变量节点,输出基础类型和数据类型
if (nodeClass == NodeClass.Variable) {
UaVariableNode varNode = client.getAddressSpace().getVariableNode(childId);
NodeId dataTypeId = varNode.getDataType();
String dataTypeStr = dataTypeId != null ? dataTypeId.toParseableString() : "未知";
String dataTypeName = client.getAddressSpace()
.getNode(dataTypeId)
.getBrowseName()
.getName();
System.out.println(" 基础类型: " + currentPath + ", 数据类型: " + dataTypeName);
}
// 递归浏览子节点
browseAndPrint(client, childId, currentPath, nodeMap);
}
}
}

浙公网安备 33010602011771号