具有历史数据访问权限的米洛OPC UA服务器



>Hy,

我是 milo (和 OPC-UA) 的新手,并尝试实现具有历史数据访问的 OPC-UA 服务器。我重用了当前的 milo 服务器示例并创建了一个历史记录节点。在此节点上,我可以查询(使用 Prosys OPC UA 客户端)空历史记录。我知道我必须自己实现历史节点的持久性。到目前为止一切顺利 - 但我找不到任何关于处理历史读取请求以及如何返回响应的信息。更准确地说,如何将HistoryData添加到HistoryReadResult

@Override
public void historyRead(HistoryReadContext context, HistoryReadDetails readDetails, TimestampsToReturn timestamps,
        List<HistoryReadValueId> readValueIds)
{
     List<HistoryReadResult> results = Lists.newArrayListWithCapacity(readValueIds.size());
     for (HistoryReadValueId readValueId : readValueIds){
         //return 3 historical entries
         DataValue v1 = new DataValue(new Variant(new Double(1)), StatusCode.GOOD, new DateTime(Date.from(Instant.now().minus(1, ChronoUnit.MINUTES))));
         DataValue v2 = new DataValue(new Variant(new Double(2)), StatusCode.GOOD, new DateTime(Date.from(Instant.now().minus(2, ChronoUnit.MINUTES))));
         DataValue v3 = new DataValue(new Variant(new Double(3)), StatusCode.GOOD,  new DateTime(Date.from(Instant.now().minus(3, ChronoUnit.MINUTES))));
         HistoryData data = new HistoryData(new DataValue[] {v1,v2,v3});
         //???
         HistoryReadResult result = new HistoryReadResult(StatusCode.GOOD, ByteString.NULL_VALUE, ??? );
         results.add(result);
     }
     context.complete(results);
}

您将需要访问规范才能成功实现历史访问服务。第 4 部分和第 11 部分。

HistoryReadResult构造函数中的最后一个参数应该是HistoryData结构。 ExtensionObject基本上是结构被编码和传输的容器。

要创建该ExtensionObject,您首先需要创建一个HistoryData(或HistoryModifiedData,取决于...请参阅规范),然后执行类似 ExtensionObject.encode(historyData) 的操作以获取完成构建HistoryReadResult所需的对象。

覆盖历史记录读取是正确的方法。

HistoryReadResult result = new HistoryReadResult(StatusCode.GOOD, ByteString.NULL_VALUE,ExtensionObject.encode(data) );

但是,在定义具有特定访问级别和历史化模式的变量节点之前,通用客户端(例如 UA-Expert)没有调用该方法,如下所示:

        Set<AccessLevel> acclevels = new LinkedHashSet<>();
        acclevels.add(AccessLevel.CurrentRead);
        acclevels.add(AccessLevel.CurrentWrite);
        acclevels.add(AccessLevel.HistoryRead);
        UaVariableNode node = new UaVariableNode.UaVariableNodeBuilder(server.getNodeMap())
                .setNodeId(new NodeId(namespaceIndex, "HelloWorld/Test/" + name))
                .setAccessLevel(ubyte(AccessLevel.getMask(acclevels)))                  
                .setUserAccessLevel(ubyte(AccessLevel.getMask(acclevels)))
                .setBrowseName(new QualifiedName(namespaceIndex, name))
                .setDisplayName(LocalizedText.english(name))
                .setDataType(typeId)
                .setTypeDefinition(Identifiers.BaseDataVariableType)
                .setHistorizing(true)
                .build();

最新更新