解释事件正确性的服务器响应

问题描述

我想将从服务器接收到的事件属性值存储在数据库中。我的问题是,如果消费者:

  1. 我不知道我的客户收到了哪种事件类型。
  2. 我不知道如何在不知道 EventType 的情况下将变体索引映射到属性

事件带有属性“EventType”,这将解决我的第一个问题。但是由于我收到许多不同的事件类型,我不知道它位于哪个变体索引中。每当创建新的 EventFilter 时,我是否应该始终在 select 子句中的索引 0 处重新定位“EventType”?

对于第二个问题,item.getMonitoringFilter().decode(client.getSerializationContext())) 提供了关于属性结构的视图,但我不确定如何使用它来将变体映射到属性。有人知道如何解决这些问题吗?

这是我使用的事件使用者代码。它取自 milo 客户端示例。

for (UaMonitoredItem monitoredItem: mItems){
                monitoredItem.setEventConsumer((item,vs) -> {
                    LOGGER.info(
                        "Event Received from: {}",item.getReadValueId().getNodeId());
                    LOGGER.info(
                        "getMonitoredItemId: {}",item.getMonitoredItemId());
                    LOGGER.info(
                        "getMonitoringFilter: {}",item.getMonitoringFilter().decode(client.getSerializationContext()));
                    for (int i = 0; i < vs.length; i++) {
                        LOGGER.info("variant[{}]:,datatype={},value={}",i,vs[i].getDataType(),vs[i].getValue());
                    }
                });
            }

提前致谢。

更新:

似乎我已经想通了,通过对 EventFilter 进行类型转换。然后可以导出更多信息,例如事件属性的 qName 或事件类型节点 ID:

ExtensionObject eObject = item.getMonitoringFilter();
EventFilter eFilter = ((EventFilter) eObject.decode(client.getSerializationContext()));
Qualifiedname qName = eFilter.getSelectClauses()[0].getbrowsePath()[0];

LiteralOperand literalOperand  = (LiteralOperand) eFilter.getWhereClause().getElements()[0]
        .getFilterOperands()[1].decode(client.getSerializationContext());
NodeId eventTypeNodeId = (NodeId) literalOperand.getValue().getValue();

解决方法

您在创建 MonitoredItem 时没有首先提供过滤器吗?为什么你需要对过滤结果进行“逆向工程”才能回到你最初所做的事情?

您在事件数据中接收的属性及其出现的顺序由您在创建 MonitoredItem 时使用的 select 子句定义。如果您选择选择 EventId 字段,那么它将始终位于相同的相应索引处。