如何过滤OPC UA Milo中UaMonitoredItem的初始事件?
问题解决方案
一、过滤初始化阶段的推送数据
你遇到的是UA服务器在监控模式从Sampling切换到Reporting时,会主动推送当前的采样值(也就是初始化时已存在的数据)。要过滤这些初始值,最可靠的方式是给每个UaMonitoredItem添加首次接收标记,跳过第一次触发的回调:
实现步骤
- 在类中维护一个线程安全的映射,记录每个监控项是否已经处理过首次推送:
private final Map<UaMonitoredItem, Boolean> firstValueReceived = new ConcurrentHashMap<>();
- 在订阅监控项时初始化标记,并在
setValueConsumer中判断过滤:
public void subscribeOnComponentsEvent(List list) { //.... //Created in MonitoringMode.Sampling to avoid race condition for (UaMonitoredItem item : monitoredItems) { allMonitoredItems.add(item); firstValueReceived.put(item, false); item.setValueConsumer((e, vs) -> { Boolean isFirst = firstValueReceived.get(e); if (Boolean.TRUE.equals(isFirst)) { // 非首次推送,记录日志 logger.info("Received from {}", e.getReadValueId().getNodeId()); } else { // 首次推送,更新标记,跳过日志 firstValueReceived.put(e, true); } }); } }
另外也可以尝试通过UA的DataChangeFilter设置仅当值发生变化时推送,但部分服务器仍会在模式切换时推送初始值,因此标记法的兼容性更强。
二、关于ManagedDataItem/ManagedEventItem的最佳实践
在Eclipse Milo客户端开发中,使用ManagedDataItem和ManagedEventItem确实属于最佳实践:
- 它们封装了底层
UaMonitoredItem的管理逻辑,包括初始化、状态跟踪、模式切换等,减少手动代码的编写量; - 提供了更简洁的API(如
setValueChangeListener),并且可以更方便地配置值变化的过滤规则; - 内置了线程安全的状态管理,降低了手动维护监控项时出现竞态条件的概率。
如果你的应用场景允许,建议替换为Managed系列的API,能大幅提升代码的可维护性。
内容的提问来源于stack exchange,提问作者Killpop3770
相关产品推荐
相关产品推荐

