如何订阅OPC UA Server对象获取所有事件(Prosys Java SDK)
监听Server对象所有事件的Prosys Java SDK实现方案
问题原因
直接订阅Server节点默认仅会接收该节点自身产生的事件,子节点的事件不会自动被包含,必须通过配置事件过滤器的筛选条件,指定要接收Server层级下所有节点的事件。
实现步骤与代码示例
1. 获取Server节点
首先获取OPC UA Server对象的NodeId,Prosys SDK可通过内置标识符直接获取:
import com.prosysopc.ua.client.UaClient; import com.prosysopc.ua.nodes.UaNode; import com.prosysopc.ua.stack.builtintypes.NodeId; import com.prosysopc.ua.stack.core.Identifiers; // 假设client已完成初始化与连接 UaNode serverNode = client.getAddressSpace().getNode(Identifiers.Server); NodeId serverNodeId = serverNode.getNodeId();
2. 构建事件过滤器
使用EventFilterBuilder创建包含层级筛选规则的过滤器,核心是添加IsDescendantOf条件,匹配所有来自Server节点及其子节点的事件:
import com.prosysopc.ua.stack.core.AttributeOperand; import com.prosysopc.ua.stack.core.ContentFilter; import com.prosysopc.ua.stack.core.ContentFilterElement; import com.prosysopc.ua.stack.core.EventFilter; import com.prosysopc.ua.stack.core.EventFilterBuilder; import com.prosysopc.ua.stack.core.FilterOperator; import com.prosysopc.ua.stack.core.LiteralOperand; EventFilterBuilder filterBuilder = new EventFilterBuilder(); // 添加需要获取的事件字段(可根据业务需求调整) filterBuilder.addSelectClause(Identifiers.EventType); filterBuilder.addSelectClause(Identifiers.SourceNode); filterBuilder.addSelectClause(Identifiers.Message); filterBuilder.addSelectClause(Identifiers.Time); filterBuilder.addSelectClause(Identifiers.Severity); // 添加筛选条件:仅接收SourceNode是Server节点或其子节点的事件 ContentFilterElement hierarchyCondition = new ContentFilterElement( FilterOperator.IsDescendantOf, new[] { // 取事件的SourceNode属性 new AttributeOperand(Identifiers.BaseEventType, Identifiers.SourceNode, null, null), // 目标节点:Server节点 new LiteralOperand(new NodeId(serverNodeId.getNamespaceIndex(), serverNodeId.getValue())) } ); filterBuilder.setWhereClause(new ContentFilter(new[] {hierarchyCondition})); EventFilter eventFilter = filterBuilder.build();
3. 创建订阅并绑定事件回调
创建订阅实例,将带有过滤器的监控项绑定到Server节点,并注册事件处理逻辑:
import com.prosysopc.ua.client.MonitoredItem; import com.prosysopc.ua.client.Subscription; import com.prosysopc.ua.stack.core.MonitoringMode; import com.prosysopc.ua.stack.core.MonitoringParameters; import com.prosysopc.ua.stack.core.MonitoredItemCreateRequest; import com.prosysopc.ua.stack.core.TimestampsToReturn; import com.prosysopc.ua.stack.builtintypes.LocalizedText; import com.prosysopc.ua.stack.builtintypes.DateTime; import com.prosysopc.ua.stack.builtintypes.UaInteger; // 创建订阅(刷新间隔1000ms,可按需调整) Subscription subscription = client.getSubscriptionManager().createSubscription(1000); // 创建事件监控项请求 MonitoredItemCreateRequest itemRequest = new MonitoredItemCreateRequest( new ReadValueId(serverNodeId, Attributes.EventNotifier, null, null), MonitoringMode.Reporting, new MonitoringParameters( UaInteger.valueOf(client.getSubscriptionManager().getNextMonitoredItemId()), 0.0, // 事件订阅采样间隔可设为0 null, UaInteger.valueOf(100), // 队列大小 true // 队列满时丢弃旧事件 ) ); // 绑定事件过滤器 itemRequest.getMonitoringParameters().setFilter(eventFilter); // 添加监控项到订阅 subscription.createMonitoredItems(TimestampsToReturn.Both, List.of(itemRequest)); // 注册事件消费者,处理收到的事件 for (MonitoredItem item : subscription.getMonitoredItems()) { item.setEventConsumer((monitoredItem, eventFields) -> { // 解析事件字段(顺序与SelectClauses定义一致) NodeId eventType = (NodeId) eventFields[0].getValue().getValue(); NodeId sourceNode = (NodeId) eventFields[1].getValue().getValue(); LocalizedText message = (LocalizedText) eventFields[2].getValue().getValue(); DateTime eventTime = (DateTime) eventFields[3].getValue().getValue(); Integer severity = (Integer) eventFields[4].getValue().getValue(); // 自定义事件处理逻辑 System.out.printf("事件触发 | 类型: %s | 来源节点: %s | 消息: %s | 时间: %s | 级别: %d%n", eventType, sourceNode, message.getText(), eventTime, severity); }); }
关键注意事项
- 确保Server节点的
EventNotifier属性支持事件订阅(默认Server节点均满足该条件)。 - 可根据业务需求调整
SelectClauses,添加或移除需要的事件属性。 - 如果需要监听特定类型的事件,可在WhereClause中追加
EventType的匹配条件。
内容的提问来源于stack exchange,提问作者WickedXXX
相关产品推荐
相关产品推荐

