问题描述
我想将从服务器接收到的事件属性值存储在数据库中。我的问题是,如果消费者:
- 我不知道我的客户收到了哪种事件类型。
- 我不知道如何在不知道 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 字段,那么它将始终位于相同的相应索引处。