C# / .NET · recipe

Read historical data in C#

Use HistoryRead with a ReadRawModifiedDetails and bound the window. Check the server claims a historical facet first, and ask for aggregates when a shift summary is what you actually want.

StackOPCFoundation/UA-.NETStandard
Version1.5.378.156 stable, 2.0.0-preview.2

The code

var details = new ReadRawModifiedDetails
{
    StartTime         = DateTime.UtcNow.AddMinutes(-10),
    EndTime           = DateTime.UtcNow,
    NumValuesPerNode  = 5,          // always bound the request
    IsReadModified    = false,
    ReturnBounds      = true,
};

var nodesToRead = new HistoryReadValueIdCollection
{
    new HistoryReadValueId { NodeId = new NodeId("Dynamic/RandomDouble", (ushort)nsIndex) },
};

session.HistoryRead(null, new ExtensionObject(details), TimestampsToReturn.Both,
    releaseContinuationPoints: false, nodesToRead,
    out HistoryReadResultCollection results, out _);

foreach (var result in results)
{
    if (StatusCode.IsBad(result.StatusCode))
    {
        Console.WriteLine($"history read failed: {result.StatusCode}");
        continue;
    }
    var data = ExtensionObject.ToEncodeable(result.HistoryData) as HistoryData;
    foreach (var dv in data.DataValues)
        Console.WriteLine($"{dv.SourceTimestamp:O} {dv.Value} [{dv.StatusCode}]");
}

What it prints

2026-09-08T03:35:00.0010000Z 41.2 [Good]
2026-09-08T03:36:00.0020000Z 43.8 [Good]
2026-09-08T03:37:00.0010000Z 39.1 [Good]
2026-09-08T03:38:00.0030000Z 44.6 [Good]
2026-09-08T03:39:00.0010000Z 42.0 [Good]

Notes

  • Set NumValuesPerNode or a short window. An unbounded read against a production historian is an incident waiting to happen.
  • Release continuation points you abandon, or you will exhaust the server's supply.
  • For OEE, use ReadProcessedDetails with an aggregate such as TimeAverage or PercentGood instead of pulling raw values. Server-side aggregation is far cheaper.
  • ReturnBounds gives you the values either side of your window, which you need to interpolate state at the boundary correctly.

What breaks first

The history read returns a bad status for the node BadHistoryOperationUnsupported
Check ServerProfileArray for a historical access facet. If it is absent, collect via subscription and store the data yourself.
Other recipes in this stack

Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.

Free download
OPC UA Troubleshooting & Integration Checklist
The field-tested checklist engineers use to diagnose certificates, ports and namespace problems fast, plus a Python (asyncua) client template.
Get the free checklist →
Free, no course, no login