64e3fbe035
v2-ci / build (push) Failing after 1m43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
Adds <summary>, <param>, <typeparam>, and <inheritdoc/> tags to public members surfaced by commentchecker — resolves 5,847 of 5,869 issues (99.6%) across three /fixdocs passes.
160 lines
8.9 KiB
C#
160 lines
8.9 KiB
C#
namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
|
|
|
/// <summary>
|
|
/// Driver capability for historical-data reads (OPC UA HistoryRead). Optional —
|
|
/// only drivers whose backends carry historian data implement this. Currently:
|
|
/// Galaxy (Wonderware Historian via the optional plugin), OPC UA Client (forward
|
|
/// to upstream server).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <see cref="ReadAtTimeAsync"/> and <see cref="ReadEventsAsync"/> are C# default interface
|
|
/// methods that throw <see cref="NotSupportedException"/> — drivers opt in by overriding so
|
|
/// a raw-only driver compiles without forcing it to provide at-time / event surfaces it
|
|
/// has no backend for. The sibling server-side surface, <see cref="IHistorianDataSource"/>,
|
|
/// declares both methods as required because a registered historian owns the full read
|
|
/// surface; the asymmetry is intentional (Core.Abstractions-008).
|
|
/// </remarks>
|
|
public interface IHistoryProvider
|
|
{
|
|
/// <summary>
|
|
/// Read raw historical samples for a single attribute over a time range.
|
|
/// The Core wraps this with continuation-point handling.
|
|
/// </summary>
|
|
/// <param name="fullReference">The full reference path to the attribute.</param>
|
|
/// <param name="startUtc">Inclusive lower bound on the time range (UTC).</param>
|
|
/// <param name="endUtc">Exclusive upper bound on the time range (UTC).</param>
|
|
/// <param name="maxValuesPerNode">Maximum number of values to return per node.</param>
|
|
/// <param name="cancellationToken">A cancellation token to stop the operation.</param>
|
|
/// <returns>A task that returns the history read result containing samples and optional continuation point.</returns>
|
|
Task<HistoryReadResult> ReadRawAsync(
|
|
string fullReference,
|
|
DateTime startUtc,
|
|
DateTime endUtc,
|
|
uint maxValuesPerNode,
|
|
CancellationToken cancellationToken);
|
|
|
|
/// <summary>
|
|
/// Read processed (aggregated) samples — interval-bucketed average / min / max / etc.
|
|
/// Optional — drivers that only support raw history can throw <see cref="NotSupportedException"/>.
|
|
/// </summary>
|
|
/// <param name="fullReference">The full reference path to the attribute.</param>
|
|
/// <param name="startUtc">Inclusive lower bound on the time range (UTC).</param>
|
|
/// <param name="endUtc">Exclusive upper bound on the time range (UTC).</param>
|
|
/// <param name="interval">The time interval for bucketing samples.</param>
|
|
/// <param name="aggregate">The aggregate function to apply to each bucket.</param>
|
|
/// <param name="cancellationToken">A cancellation token to stop the operation.</param>
|
|
/// <returns>A task that returns the history read result containing aggregated samples and optional continuation point.</returns>
|
|
Task<HistoryReadResult> ReadProcessedAsync(
|
|
string fullReference,
|
|
DateTime startUtc,
|
|
DateTime endUtc,
|
|
TimeSpan interval,
|
|
HistoryAggregateType aggregate,
|
|
CancellationToken cancellationToken);
|
|
|
|
/// <summary>
|
|
/// Read one sample per requested timestamp — OPC UA HistoryReadAtTime service. The
|
|
/// driver interpolates (or returns the prior-boundary sample) when no exact match
|
|
/// exists. Optional; drivers that can't interpolate throw <see cref="NotSupportedException"/>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Default implementation throws. Drivers opt in by overriding; keeps existing
|
|
/// <c>IHistoryProvider</c> implementations compiling without forcing a ReadAtTime path
|
|
/// they may not have a backend for.
|
|
/// </remarks>
|
|
/// <param name="fullReference">The full reference path to the attribute.</param>
|
|
/// <param name="timestampsUtc">The list of timestamps at which to read values.</param>
|
|
/// <param name="cancellationToken">A cancellation token to stop the operation.</param>
|
|
/// <returns>A task that returns the history read result containing samples at the requested times.</returns>
|
|
Task<HistoryReadResult> ReadAtTimeAsync(
|
|
string fullReference,
|
|
IReadOnlyList<DateTime> timestampsUtc,
|
|
CancellationToken cancellationToken)
|
|
=> throw new NotSupportedException(
|
|
$"{GetType().Name} does not implement ReadAtTimeAsync. " +
|
|
"Drivers whose backends support at-time reads override this method.");
|
|
|
|
/// <summary>
|
|
/// Read historical alarm/event records — OPC UA HistoryReadEvents service. Distinct
|
|
/// from the live event stream — historical rows come from an event historian (Galaxy's
|
|
/// Alarm Provider history log, etc.) rather than the driver's active subscription.
|
|
/// </summary>
|
|
/// <param name="sourceName">
|
|
/// Optional filter: null means "all sources", otherwise restrict to events from that
|
|
/// source-object name. Drivers may ignore the filter if the backend doesn't support it.
|
|
/// </param>
|
|
/// <param name="startUtc">Inclusive lower bound on <c>EventTimeUtc</c>.</param>
|
|
/// <param name="endUtc">Exclusive upper bound on <c>EventTimeUtc</c>.</param>
|
|
/// <param name="maxEvents">
|
|
/// Upper cap on returned events — the driver's backend enforces this. The type is
|
|
/// <see cref="int"/> rather than <see cref="uint"/> (which the sibling raw / processed
|
|
/// reads use for <c>maxValuesPerNode</c>) because callers and downstream historian
|
|
/// adapters historically treat <c>maxEvents <= 0</c> as a sentinel meaning
|
|
/// "use the backend's default cap" (see <c>WonderwareHistorianClient</c> /
|
|
/// <c>HistorianDataSource</c>). The asymmetry is intentional — Core.Abstractions-006.
|
|
/// </param>
|
|
/// <param name="cancellationToken">Request cancellation.</param>
|
|
/// <remarks>
|
|
/// Default implementation throws. Only drivers with an event historian (Galaxy via the
|
|
/// Wonderware Alarm & Events log) override. Modbus / the OPC UA Client driver stay
|
|
/// with the default and let callers see <c>BadHistoryOperationUnsupported</c>.
|
|
///
|
|
/// Note the type asymmetry with <see cref="ReadRawAsync"/> /
|
|
/// <see cref="ReadProcessedAsync"/> (both use <c>uint maxValuesPerNode</c>): event
|
|
/// readers accept a signed <c>int maxEvents</c> so callers can pass 0 / negative as a
|
|
/// "use default cap" sentinel without an extra parameter or overload.
|
|
/// </remarks>
|
|
Task<HistoricalEventsResult> ReadEventsAsync(
|
|
string? sourceName,
|
|
DateTime startUtc,
|
|
DateTime endUtc,
|
|
int maxEvents,
|
|
CancellationToken cancellationToken)
|
|
=> throw new NotSupportedException(
|
|
$"{GetType().Name} does not implement ReadEventsAsync. " +
|
|
"Drivers whose backends have an event historian override this method.");
|
|
}
|
|
|
|
/// <summary>Result of a HistoryRead call.</summary>
|
|
/// <param name="Samples">Returned samples in chronological order.</param>
|
|
/// <param name="ContinuationPoint">Opaque token for the next call when more samples are available; null when complete.</param>
|
|
public sealed record HistoryReadResult(
|
|
IReadOnlyList<DataValueSnapshot> Samples,
|
|
byte[]? ContinuationPoint);
|
|
|
|
/// <summary>Aggregate function for processed history reads. Mirrors OPC UA Part 13 standard aggregates.</summary>
|
|
public enum HistoryAggregateType
|
|
{
|
|
Average,
|
|
Minimum,
|
|
Maximum,
|
|
Total,
|
|
Count,
|
|
}
|
|
|
|
/// <summary>
|
|
/// One row returned by <see cref="IHistoryProvider.ReadEventsAsync"/> — a historical
|
|
/// alarm/event record, not the OPC UA live-event stream. Fields match the minimum set the
|
|
/// Server needs to populate a <c>HistoryEventFieldList</c> for HistoryReadEvents responses.
|
|
/// </summary>
|
|
/// <param name="EventId">Stable unique id for the event — driver-specific format.</param>
|
|
/// <param name="SourceName">Source object that emitted the event. May differ from the <c>sourceName</c> filter the caller passed (fuzzy matches).</param>
|
|
/// <param name="EventTimeUtc">Process-side timestamp — when the event actually occurred.</param>
|
|
/// <param name="ReceivedTimeUtc">Historian-side timestamp — when the historian persisted the row; may lag <paramref name="EventTimeUtc"/> by the historian's buffer flush cadence.</param>
|
|
/// <param name="Message">Human-readable message text.</param>
|
|
/// <param name="Severity">OPC UA severity (1-1000). Drivers map their native priority scale onto this range.</param>
|
|
public sealed record HistoricalEvent(
|
|
string EventId,
|
|
string? SourceName,
|
|
DateTime EventTimeUtc,
|
|
DateTime ReceivedTimeUtc,
|
|
string? Message,
|
|
ushort Severity);
|
|
|
|
/// <summary>Result of a <see cref="IHistoryProvider.ReadEventsAsync"/> call.</summary>
|
|
/// <param name="Events">Events in chronological order by <c>EventTimeUtc</c>.</param>
|
|
/// <param name="ContinuationPoint">Opaque token for the next call when more events are available; null when complete.</param>
|
|
public sealed record HistoricalEventsResult(
|
|
IReadOnlyList<HistoricalEvent> Events,
|
|
byte[]? ContinuationPoint);
|