opcua-solution-net
opcua-solution-net copied to clipboard
HistoricalAccess OPC UA Server workshop questions
I've completed the steps in 4.8 Tutorial “HistoricalAccess OPC UA Server” but I'm confused about how a Historizing tag returns historical data.
I see that the demo includes overridding methods like protected override void HistoryReadRawModified, which it describes as "Those methods then have to handle the access to the historical data".
However, the PDF leaves the methods throwing NotImplementedException.
Do I understand correctly that
- these overridden handlers are the only way to return historical data- there is no default implementation inside the SDK
- the implementation should get the query details from
details.timestampsToReturn, andnodesToRead - and add the appropriate historical data to
results, with one HistoryReadResult per node?
if that's correct, can you clarify a few more details?
a. what is the difference between nodesToRead and nodesToProcess?
b. what is the correct structure for results ?
c. I see results enters the method with a single value- what should I do with that?
d. I'm also seeing errors enter the method with a BadHistoryOperationUnsupported ServiceResult- is that normal and I'm supposed to remove it if it IS supported, or does that mean I messed up the capabilities?
e. what is cache ? it seems to be empty...
Thanks for your patience!
Historical Access and HistoricalEvents is only a base implementation yet. We will update the documentation and samples soon.
In a first step you can check the OPC UA Online Reference at OPC UA Online Reference. This might answer already several of your questions.
Unfortunately, I'm not seeing much directly applicable information in the Online Reference- there's a hint that results[x].HistoryData should itself be an Opc.Ua.DataValue array, which seems reasonable, but still leaves a lot of questions on the correct implementation.
Can you elaborate on what you mean by "base implementation" ? what limitations should I expect?
All services for HistoricalAccess and HistoricalEvents are implemented but no additional helper methods and not yet an example.
We are trying to add a simple example including documentation soon.
I've tried to create a simple toy using fake data, but I'm completely stuck on how to provide results- fooling around with DataValue[], DataValueCollection, DataValue, etc doesn't give me anything I can set in HistoryReadResult.HistoryData or HistoryData.Body. Unfortunately, HistoryReadRawModified is a critical use case for me- do you have any timeline when simple HistoricalAccess examples will be available? weeks? months? next year?
Thanks!
PS- the code I'm trying with, ignoring almost all edge cases & conditions:
protected override void HistoryReadRawModified(
UaServerContext context,
ReadRawModifiedDetails details,
TimestampsToReturn timestampsToReturn,
IList<HistoryReadValueId> nodesToRead,
IList<HistoryReadResult> results,
IList<ServiceResult> errors,
List<UaNodeHandle> nodesToProcess,
IDictionary<NodeId, NodeState> cache)
{
errors.Clear();
try
{
nodesToProcess.ForEach(n =>
{
var node = dynamicNodes_.FirstOrDefault(dn => dn.NodeId == n.NodeId);
var timestamp = details.EndTime;
var item = new HistoryReadResult() {HistoryData = new ExtensionObject(n.NodeId)};
var data = new DataValueCollection();
var count = details.NumValuesPerNode;
if (count == 0)
count = 10000;
for (int i = 0; i < count; i++)
{
var value = new DataValue()
{
SourceTimestamp = timestamp,
ServerTimestamp = timestamp,
Value = i
};
data.Add(value);
item.HistoryData.Body = value;
if (timestamp <= details.StartTime)
break;
timestamp = timestamp.AddSeconds(-1);
}
results.Add(item);
});
}
catch (Exception ex)
{
}
}
A first version implementing HistoryReadRawModified is available now:
HistoricalAccessSampleServer.zip
It doesn't implement DataAccess or dynamic values. But hopefully that helps for the start.
Thanks! That's extremely helpful for evaluating; I can understand the actual method expectation now, and I'm satisfied that I can create my own solution if need be. I'm very interested in a detailed exploration of the implementation. and I can definitely see helper methods simplifying the requirements a lot, but that's not quite so urgent now that I can understand and step through the fundamental API.
With update to 2.3.11 (see #26) HistoricalAccess example is complete. The next major version will then simplify the HistoricalAccess handling