如何在Eclipse Milo中获取OPC UA节点的名称
你在回调中看到ReadValueId里dataEncoding的name字段为空属于正常情况,该字段用于定义值的编码格式,和节点本身的名称没有关系。OPC UA协议中,节点的名称(分为浏览名BrowseName和展示名DisplayName两种,通常业务场景下用的变量名指DisplayName)属于节点元数据属性,不会随数据变更的通知报文一起返回,需要主动读取后缓存使用。
可用的解决方法
方法1:订阅前批量读取节点元数据缓存
在创建订阅项之前,先批量读取所有待订阅节点的DisplayName属性,本地维护NodeId到节点名称的映射关系,回调时直接通过NodeId查询映射即可,示例代码如下:
回调时使用缓存的映射:// 待订阅的节点ID列表,根据你的实际业务替换 List<NodeId> subscribeNodeIds = Arrays.asList(new NodeId(4, 4), /* 其他待订阅节点ID */); // 构造读取DisplayName的请求 List<ReadValueId> metaReadRequests = subscribeNodeIds.stream() .map(nodeId -> new ReadValueId( nodeId, AttributeId.DisplayName.uid(), null, QualifiedName.NULL_VALUE )).collect(Collectors.toList()); // 执行批量读取,构建映射关系 UaReadResponse metaReadResp = client.read(metaReadRequests, 0.0).get(); Map<NodeId, String> nodeNameMap = new HashMap<>(); for (int i = 0; i < subscribeNodeIds.size(); i++) { DataValue result = metaReadResp.getResults().get(i); if (result.getStatusCode().isGood()) { LocalizedText displayName = (LocalizedText) result.getValue().getValue(); nodeNameMap.put(subscribeNodeIds.get(i), displayName.getText()); } else { nodeNameMap.put(subscribeNodeIds.get(i), "未知节点"); } }subscription.addDataChangeListener((items, values) -> { for (int i = 0; i < items.size(); i++) { NodeId currentNodeId = items.get(i).getNodeId(); String nodeName = nodeNameMap.get(currentNodeId); logger.info( "subscription value received: 节点名称={}, value={}", nodeName, values.get(i).getValue() ); } });方法2:浏览地址空间时直接缓存名称
如果你是先通过浏览OPC UA地址空间拿到的待订阅节点,在浏览返回的节点信息中已经包含了BrowseName和DisplayName属性,直接在浏览阶段就把映射关系存到本地即可,无需额外发起读请求。
第三方OPC客户端能直接展示节点名称,是因为这类工具在浏览节点阶段就已经缓存了所有节点的元数据,展示订阅数据时直接关联了本地缓存的名称,并非从数据变更通知中直接获取。
内容的提问来源于stack exchange,提问作者Jure
相关产品推荐
相关产品推荐

