[英]Milo OPC UA Server with Historical Data Access
Hy, HY,
I'm new to milo (and OPC-UA) and try to implement an OPC-UA server with Historical Data Access. 我是milo (和OPC-UA)的新手,并尝试通过历史数据访问实现OPC-UA服务器。 I reused the current milo server example and create a history node. 我重用了当前的milo服务器示例并创建了一个历史节点。 On this node I can query (with the Prosys OPC UA Client) the empty history. 在此节点上,我可以(使用Prosys OPC UA客户端)查询空历史记录。 I know that I have to implement the persistency of the history nodes by myself. 我知道我必须自己实现历史节点的持久性。 So far so good – but I could not found any information about to handle the history read request and how to return the response. 到目前为止,一切都很好–但是我找不到任何有关处理历史读取请求以及如何返回响应的信息。 More precisely how to add the HistoryData
to an HistoryReadResult
更确切地说,如何将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);
}
You're going to need access to the spec to successfully implement historical access services. 您将需要访问规范才能成功实现历史访问服务。 Part 4 and Part 11. 第4部分和第11部分。
The last parameter in the HistoryReadResult
constructor is supposed to be a HistoryData
structure. HistoryReadResult
构造函数中的最后一个参数应该是HistoryData
结构。 ExtensionObject
is basically the container that structures are encoded and transferred in. ExtensionObject
是对结构进行编码和传输的容器。
To create that ExtensionObject
you would first create a HistoryData
(or HistoryModifiedData
, depends... see the spec) and then do something like ExtensionObject.encode(historyData)
to get the object you need to finish building the HistoryReadResult
. 要创建该ExtensionObject
您首先要创建一个HistoryData
(或HistoryModifiedData
,取决于...请参见规范),然后执行类似ExtensionObject.encode(historyData)
来获取完成构建HistoryReadResult
所需的对象。
Overrides historyRead is the correct way to do. 覆盖historyRead是正确的方法。
HistoryReadResult result = new HistoryReadResult(StatusCode.GOOD, ByteString.NULL_VALUE,ExtensionObject.encode(data) );
However method was not called by generic client such as UA-Expert before defining my variableNode with specific AccessLevel and Historizing mode like this : 但是,在使用特定的AccessLevel和Historizing模式定义我的variableNode之前,通用客户端(例如UA-Expert)未调用method:
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();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.