docs: backfill XML documentation across 756 files
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.
This commit is contained in:
Joseph Doherty
2026-05-28 08:10:17 -04:00
parent f9fc7dd2e1
commit 64e3fbe035
756 changed files with 9876 additions and 96 deletions
@@ -50,6 +50,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
private readonly System.Collections.Concurrent.ConcurrentDictionary<long, RemoteAlarmSubscription> _alarmSubscriptions = new();
private long _nextAlarmSubscriptionId;
/// <summary>Occurs when an alarm event is received from the remote OPC UA server.</summary>
public event EventHandler<AlarmEventArgs>? OnAlarmEvent;
// ---- ISubscribable + IHostConnectivityProbe state ----
@@ -61,7 +62,9 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
private DateTime _hostStateChangedUtc = DateTime.UtcNow;
private KeepAliveEventHandler? _keepAliveHandler;
/// <summary>Occurs when a monitored item's data value changes on the remote OPC UA server.</summary>
public event EventHandler<DataChangeEventArgs>? OnDataChange;
/// <summary>Occurs when the host connectivity status of the remote OPC UA server changes.</summary>
public event EventHandler<HostStatusChangedEventArgs>? OnHostStatusChanged;
// OPC UA StatusCode constants the driver surfaces for local-side faults. Upstream-server
@@ -118,9 +121,14 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// </summary>
private NamespaceMap? _namespaceMap;
/// <summary>Gets the stable logical identifier for this driver instance from the config database.</summary>
public string DriverInstanceId => _driverInstanceId;
/// <summary>Gets the driver type identifier.</summary>
public string DriverType => "OpcUaClient";
/// <summary>Initializes the OPC UA client driver with the given configuration.</summary>
/// <param name="driverConfigJson">JSON-serialized driver configuration.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
_health = new DriverHealth(DriverState.Initializing, null, null);
@@ -294,6 +302,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// non-empty; otherwise fall back to <c>EndpointUrl</c> as a single-URL shortcut so
/// existing single-endpoint configs keep working without migration.
/// </summary>
/// <param name="opts">Driver options containing endpoint configuration.</param>
internal static IReadOnlyList<string> ResolveEndpointCandidates(OpcUaClientDriverOptions opts)
{
if (opts.EndpointUrls is { Count: > 0 }) return opts.EndpointUrls;
@@ -308,6 +317,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// UNS mapping table is meaningless and rejected. Throwing here surfaces the
/// misconfiguration as a draft-validation failure rather than a runtime surprise.
/// </summary>
/// <param name="opts">Driver options containing namespace configuration.</param>
internal static void ValidateNamespaceKind(OpcUaClientDriverOptions opts)
{
switch (opts.TargetNamespaceKind)
@@ -341,6 +351,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// every endpoint attempt — generating it N times would re-unlock the user cert's
/// private key N times, wasteful + keeps the password in memory longer.
/// </summary>
/// <param name="options">Driver options containing authentication configuration.</param>
internal static UserIdentity BuildUserIdentity(OpcUaClientDriverOptions options) =>
options.AuthType switch
{
@@ -443,6 +454,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// lacks a private key (the private key is required to sign the user-token
/// challenge during session activation).
/// </summary>
/// <param name="options">Driver options containing certificate configuration.</param>
internal static UserIdentity BuildCertificateIdentity(OpcUaClientDriverOptions options)
{
if (string.IsNullOrWhiteSpace(options.UserCertificatePath))
@@ -469,6 +481,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
}
/// <summary>Convert a driver <see cref="OpcUaSecurityPolicy"/> to the OPC UA policy URI.</summary>
/// <param name="policy">The driver security policy to map.</param>
internal static string MapSecurityPolicy(OpcUaSecurityPolicy policy) => policy switch
{
OpcUaSecurityPolicy.None => SecurityPolicies.None,
@@ -483,12 +496,17 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
private static string ShortPolicyName(string policyUri) =>
policyUri?.Substring(policyUri.LastIndexOf('#') + 1) ?? "(null)";
/// <summary>Reinitializes the driver with new configuration, shutting down and restarting the session.</summary>
/// <param name="driverConfigJson">JSON-serialized driver configuration.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
await ShutdownAsync(cancellationToken).ConfigureAwait(false);
await InitializeAsync(driverConfigJson, cancellationToken).ConfigureAwait(false);
}
/// <summary>Gracefully shuts down the OPC UA session, unsubscribing all active monitoring items and closing the connection.</summary>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task ShutdownAsync(CancellationToken cancellationToken)
{
// Tear down remote subscriptions first — otherwise Session.Close will try and may fail
@@ -564,6 +582,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
}
/// <summary>Gets the current health status of the OPC UA client driver.</summary>
public DriverHealth GetHealth() => _health;
/// <summary>
@@ -584,6 +603,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// flush here resets the footprint counter and signals the Core that re-discovery
/// will rebuild it cleanly from the remote server.
/// </summary>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public Task FlushOptionalCachesAsync(CancellationToken cancellationToken)
{
_discoveredNodeCount = 0;
@@ -592,6 +612,9 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
// ---- IReadable ----
/// <summary>Reads the current values of the specified nodes from the remote OPC UA server.</summary>
/// <param name="fullReferences">Fully-qualified node identifiers to read.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task<IReadOnlyList<DataValueSnapshot>> ReadAsync(
IReadOnlyList<string> fullReferences, CancellationToken cancellationToken)
{
@@ -680,6 +703,9 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
// ---- IWritable ----
/// <summary>Writes values to the specified nodes on the remote OPC UA server.</summary>
/// <param name="writes">Write requests specifying nodes and values to write.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task<IReadOnlyList<WriteResult>> WriteAsync(
IReadOnlyList<Core.Abstractions.WriteRequest> writes, CancellationToken cancellationToken)
{
@@ -772,6 +798,9 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// corrected (driver-specs.md §8). Empty + malformed strings return false; the driver
/// surfaces that as <see cref="StatusBadNodeIdInvalid"/> without a wire round-trip.
/// </summary>
/// <param name="session">The OPC UA session to resolve the node ID against.</param>
/// <param name="fullReference">The full reference string to parse.</param>
/// <param name="nodeId">The parsed node ID when successful.</param>
internal static bool TryParseNodeId(ISession session, string fullReference, out NodeId nodeId) =>
NamespaceMap.TryResolve(session, fullReference, out nodeId);
@@ -788,6 +817,9 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
// ---- ITagDiscovery ----
/// <summary>Discovers the remote OPC UA server's address space and materializes it through the supplied builder.</summary>
/// <param name="builder">Address space builder for materializing discovered nodes.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(builder);
@@ -1053,6 +1085,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// string rendering but the cascading-quality path still preserves upstream
/// StatusCode + timestamps.
/// </summary>
/// <param name="dataType">The OPC UA data type NodeId to map.</param>
internal static DriverDataType MapUpstreamDataType(NodeId dataType)
{
if (dataType == DataTypeIds.Boolean) return DriverDataType.Boolean;
@@ -1080,6 +1113,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// layer can gate writes off. CurrentWrite-capable variables surface as
/// <see cref="SecurityClassification.Operate"/>; read-only as <see cref="SecurityClassification.ViewOnly"/>.
/// </summary>
/// <param name="accessLevel">The OPC UA access level bitmask.</param>
internal static SecurityClassification MapAccessLevelToSecurityClass(byte accessLevel)
{
const byte CurrentWrite = 2; // AccessLevels.CurrentWrite = 0x02
@@ -1090,6 +1124,10 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
// ---- ISubscribable ----
/// <summary>Subscribes to monitored value changes on the specified nodes from the remote OPC UA server.</summary>
/// <param name="fullReferences">Fully-qualified node identifiers to monitor.</param>
/// <param name="publishingInterval">Desired minimum interval between publish cycles.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task<ISubscriptionHandle> SubscribeAsync(
IReadOnlyList<string> fullReferences, TimeSpan publishingInterval, CancellationToken cancellationToken)
{
@@ -1160,6 +1198,9 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
return handle;
}
/// <summary>Unsubscribes from monitored value changes for the specified subscription handle.</summary>
/// <param name="handle">The subscription handle to unsubscribe.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task UnsubscribeAsync(ISubscriptionHandle handle, CancellationToken cancellationToken)
{
if (handle is not OpcUaSubscriptionHandle h) return;
@@ -1231,6 +1272,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
private sealed record OpcUaSubscriptionHandle(long Id) : ISubscriptionHandle
{
/// <summary>Gets the diagnostic identifier for this subscription.</summary>
public string DiagnosticId => $"opcua-sub-{Id}";
}
@@ -1248,6 +1290,9 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
private const int AlarmFieldTime = 5;
private const int AlarmFieldConditionId = 6;
/// <summary>Subscribes to alarm and event notifications from the remote OPC UA server.</summary>
/// <param name="sourceNodeIds">Source node identifiers to subscribe alarms from.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task<IAlarmSubscriptionHandle> SubscribeAlarmsAsync(
IReadOnlyList<string> sourceNodeIds, CancellationToken cancellationToken)
{
@@ -1333,6 +1378,9 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
return handle;
}
/// <summary>Unsubscribes from alarm and event notifications for the specified alarm subscription handle.</summary>
/// <param name="handle">The alarm subscription handle to unsubscribe.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken)
{
if (handle is not OpcUaAlarmSubscriptionHandle h) return;
@@ -1352,6 +1400,9 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
finally { _gate.Release(); }
}
/// <summary>Acknowledges multiple alarms by calling the remote OPC UA server's Acknowledge method.</summary>
/// <param name="acknowledgements">List of alarm acknowledgement requests.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task AcknowledgeAsync(
IReadOnlyList<AlarmAcknowledgeRequest> acknowledgements, CancellationToken cancellationToken)
{
@@ -1465,6 +1516,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// <see cref="AlarmSeverity"/> bucket. Thresholds match the OPC UA A&amp;C Part 9
/// guidance: 1-200 Low, 201-500 Medium, 501-800 High, 801-1000 Critical.
/// </summary>
/// <param name="opcSeverity">The OPC UA severity value (1-1000).</param>
internal static AlarmSeverity MapSeverity(ushort opcSeverity) => opcSeverity switch
{
<= 200 => AlarmSeverity.Low,
@@ -1487,11 +1539,18 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
private sealed record OpcUaAlarmSubscriptionHandle(long Id) : IAlarmSubscriptionHandle
{
/// <summary>Gets the diagnostic identifier for this alarm subscription.</summary>
public string DiagnosticId => $"opcua-alarm-sub-{Id}";
}
// ---- IHistoryProvider (passthrough to upstream server) ----
/// <summary>Reads raw historical data from the remote OPC UA server.</summary>
/// <param name="fullReference">Fully-qualified node identifier to read history for.</param>
/// <param name="startUtc">Start time in UTC for the history query.</param>
/// <param name="endUtc">End time in UTC for the history query.</param>
/// <param name="maxValuesPerNode">Maximum number of values to return.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task<Core.Abstractions.HistoryReadResult> ReadRawAsync(
string fullReference, DateTime startUtc, DateTime endUtc, uint maxValuesPerNode,
CancellationToken cancellationToken)
@@ -1508,6 +1567,13 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
.ConfigureAwait(false);
}
/// <summary>Reads processed (aggregated) historical data from the remote OPC UA server.</summary>
/// <param name="fullReference">Fully-qualified node identifier to read history for.</param>
/// <param name="startUtc">Start time in UTC for the history query.</param>
/// <param name="endUtc">End time in UTC for the history query.</param>
/// <param name="interval">Time interval for aggregation.</param>
/// <param name="aggregate">The aggregation function to apply.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task<Core.Abstractions.HistoryReadResult> ReadProcessedAsync(
string fullReference, DateTime startUtc, DateTime endUtc, TimeSpan interval,
HistoryAggregateType aggregate, CancellationToken cancellationToken)
@@ -1524,6 +1590,10 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
.ConfigureAwait(false);
}
/// <summary>Reads historical data at specific timestamps from the remote OPC UA server.</summary>
/// <param name="fullReference">Fully-qualified node identifier to read history for.</param>
/// <param name="timestampsUtc">List of specific timestamps to read values at.</param>
/// <param name="cancellationToken">Cancellation token for the operation.</param>
public async Task<Core.Abstractions.HistoryReadResult> ReadAtTimeAsync(
string fullReference, IReadOnlyList<DateTime> timestampsUtc, CancellationToken cancellationToken)
{
@@ -1594,6 +1664,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
}
/// <summary>Map <see cref="HistoryAggregateType"/> to the OPC UA Part 13 standard aggregate NodeId.</summary>
/// <param name="aggregate">The aggregation function type to map.</param>
internal static NodeId MapAggregateToNodeId(HistoryAggregateType aggregate) => aggregate switch
{
HistoryAggregateType.Average => ObjectIds.AggregateFunction_Average,
@@ -1623,6 +1694,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
?? ResolveEndpointCandidates(_options).FirstOrDefault()
?? _options.EndpointUrl;
/// <summary>Gets the current connectivity status of the remote OPC UA server host.</summary>
public IReadOnlyList<HostConnectivityStatus> GetHostStatuses()
{
lock (_probeLock)
@@ -1854,6 +1926,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
_gate.Dispose();
}
/// <summary>Asynchronously disposes the driver and releases all associated resources.</summary>
public async ValueTask DisposeAsync()
{
if (_disposed) return;