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
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:
@@ -40,13 +40,26 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
private AbCipAlarmProjection _alarmProjection;
|
||||
private DriverHealth _health = new(DriverState.Unknown, null, null);
|
||||
|
||||
/// <summary>Occurs when a subscribed tag's value changes.</summary>
|
||||
public event EventHandler<DataChangeEventArgs>? OnDataChange;
|
||||
|
||||
/// <summary>Occurs when a device's host connectivity status changes.</summary>
|
||||
public event EventHandler<HostStatusChangedEventArgs>? OnHostStatusChanged;
|
||||
|
||||
/// <summary>Occurs when an alarm event is raised.</summary>
|
||||
public event EventHandler<AlarmEventArgs>? OnAlarmEvent;
|
||||
|
||||
/// <summary>Internal seam for the alarm projection to raise events through the driver.</summary>
|
||||
/// <param name="args">The alarm event arguments.</param>
|
||||
internal void InvokeAlarmEvent(AlarmEventArgs args) => OnAlarmEvent?.Invoke(this, args);
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AbCipDriver"/> class.</summary>
|
||||
/// <param name="options">The driver configuration options.</param>
|
||||
/// <param name="driverInstanceId">A unique identifier for this driver instance.</param>
|
||||
/// <param name="tagFactory">Optional factory for creating tag runtimes; uses libplctag default if null.</param>
|
||||
/// <param name="enumeratorFactory">Optional factory for enumerating tags; uses libplctag default if null.</param>
|
||||
/// <param name="templateReaderFactory">Optional factory for reading UDT templates; uses libplctag default if null.</param>
|
||||
/// <param name="logger">Optional logger; uses null logger if not provided.</param>
|
||||
public AbCipDriver(AbCipDriverOptions options, string driverInstanceId,
|
||||
IAbCipTagFactory? tagFactory = null,
|
||||
IAbCipTagEnumeratorFactory? enumeratorFactory = null,
|
||||
@@ -74,6 +87,10 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// additional network traffic. <c>null</c> on template-not-found / decode failure so
|
||||
/// callers can fall back to declaration-driven UDT fan-out.
|
||||
/// </summary>
|
||||
/// <param name="deviceHostAddress">The host address of the device to read the template from.</param>
|
||||
/// <param name="templateInstanceId">The instance ID of the UDT template to fetch.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>The UDT shape if found and decoded successfully; null otherwise.</returns>
|
||||
internal async Task<AbCipUdtShape?> FetchUdtShapeAsync(
|
||||
string deviceHostAddress, uint templateInstanceId, CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -113,7 +130,10 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// </summary>
|
||||
internal AbCipTemplateCache TemplateCache => _templateCache;
|
||||
|
||||
/// <summary>Gets the unique identifier for this driver instance.</summary>
|
||||
public string DriverInstanceId => _driverInstanceId;
|
||||
|
||||
/// <summary>Gets the driver type identifier.</summary>
|
||||
public string DriverType => "AbCip";
|
||||
|
||||
/// <summary>
|
||||
@@ -127,6 +147,9 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// unit tests — keep those options. The driver's address-space + runtime state is then
|
||||
/// built from the effective <see cref="_options"/>.
|
||||
/// </summary>
|
||||
/// <param name="driverConfigJson">The driver configuration as JSON; empty or "{}" means no override.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A task representing the asynchronous initialization.</returns>
|
||||
public Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
|
||||
{
|
||||
_health = new DriverHealth(DriverState.Initializing, null, null);
|
||||
@@ -221,6 +244,10 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>Reinitialize the driver by shutting down and reinitializing with new configuration.</summary>
|
||||
/// <param name="driverConfigJson">The new driver configuration as JSON.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A task representing the asynchronous reinitialization.</returns>
|
||||
public async Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
|
||||
{
|
||||
await ShutdownAsync(cancellationToken).ConfigureAwait(false);
|
||||
@@ -235,6 +262,8 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// dictionary (Driver.AbCip-008). Idempotent — safe to call twice (e.g. ShutdownAsync
|
||||
/// from ReinitializeAsync followed by DisposeAsync).
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A task representing the asynchronous shutdown.</returns>
|
||||
public async Task ShutdownAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _alarmProjection.DisposeAsync().ConfigureAwait(false);
|
||||
@@ -276,10 +305,19 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
|
||||
// ---- ISubscribable (polling overlay via shared engine) ----
|
||||
|
||||
/// <summary>Subscribe to value changes for the specified tag references.</summary>
|
||||
/// <param name="fullReferences">The tag references to subscribe to.</param>
|
||||
/// <param name="publishingInterval">The interval at which to publish changes.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A handle representing the subscription.</returns>
|
||||
public Task<ISubscriptionHandle> SubscribeAsync(
|
||||
IReadOnlyList<string> fullReferences, TimeSpan publishingInterval, CancellationToken cancellationToken) =>
|
||||
Task.FromResult(_poll.Subscribe(fullReferences, publishingInterval));
|
||||
|
||||
/// <summary>Unsubscribe from value changes using a subscription handle.</summary>
|
||||
/// <param name="handle">The subscription handle to unsubscribe.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A completed task.</returns>
|
||||
public Task UnsubscribeAsync(ISubscriptionHandle handle, CancellationToken cancellationToken)
|
||||
{
|
||||
_poll.Unsubscribe(handle);
|
||||
@@ -297,6 +335,9 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// <c>false</c> (the default), returns a handle wrapping a no-op subscription so
|
||||
/// capability negotiation still works; <see cref="OnAlarmEvent"/> never fires.
|
||||
/// </summary>
|
||||
/// <param name="sourceNodeIds">The node IDs of alarm sources to subscribe to.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A handle representing the alarm subscription.</returns>
|
||||
public Task<IAlarmSubscriptionHandle> SubscribeAlarmsAsync(
|
||||
IReadOnlyList<string> sourceNodeIds, CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -308,11 +349,19 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
return _alarmProjection.SubscribeAsync(sourceNodeIds, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>Unsubscribe from alarm events.</summary>
|
||||
/// <param name="handle">The alarm subscription handle.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A completed task.</returns>
|
||||
public Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken) =>
|
||||
_options.EnableAlarmProjection
|
||||
? _alarmProjection.UnsubscribeAsync(handle, cancellationToken)
|
||||
: Task.CompletedTask;
|
||||
|
||||
/// <summary>Acknowledge alarms.</summary>
|
||||
/// <param name="acknowledgements">The alarm acknowledgements to process.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A completed task.</returns>
|
||||
public Task AcknowledgeAsync(
|
||||
IReadOnlyList<AlarmAcknowledgeRequest> acknowledgements, CancellationToken cancellationToken) =>
|
||||
_options.EnableAlarmProjection
|
||||
@@ -321,6 +370,8 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
|
||||
// ---- IHostConnectivityProbe ----
|
||||
|
||||
/// <summary>Gets the connectivity status of all configured devices.</summary>
|
||||
/// <returns>A read-only list of host connectivity statuses.</returns>
|
||||
public IReadOnlyList<HostConnectivityStatus> GetHostStatuses() =>
|
||||
[.. _devices.Values.Select(s => new HostConnectivityStatus(s.Options.HostAddress, s.HostState, s.HostStateChangedUtc))];
|
||||
|
||||
@@ -395,6 +446,8 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// first configured device's host address rather than throwing — the invoker handles the
|
||||
/// mislookup at the capability level when the actual read returns BadNodeIdUnknown.
|
||||
/// </summary>
|
||||
/// <param name="fullReference">The full tag reference to resolve.</param>
|
||||
/// <returns>The device host address for the tag.</returns>
|
||||
public string ResolveHost(string fullReference)
|
||||
{
|
||||
if (_tagsByName.TryGetValue(fullReference, out var def))
|
||||
@@ -411,6 +464,9 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// <c>BadCommunicationError</c>. The driver health surface is updated per-call so the
|
||||
/// Admin UI sees a tight feedback loop between read failures + the driver's state.
|
||||
/// </summary>
|
||||
/// <param name="fullReferences">The tag references to read.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A read-only list of data value snapshots.</returns>
|
||||
public async Task<IReadOnlyList<DataValueSnapshot>> ReadAsync(
|
||||
IReadOnlyList<string> fullReferences, CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -584,6 +640,9 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// Non-writable configurations surface as <c>BadNotWritable</c>; type-conversion failures
|
||||
/// as <c>BadTypeMismatch</c>; transport errors as <c>BadCommunicationError</c>.
|
||||
/// </summary>
|
||||
/// <param name="writes">The write requests to execute.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A read-only list of write results.</returns>
|
||||
public async Task<IReadOnlyList<WriteResult>> WriteAsync(
|
||||
IReadOnlyList<WriteRequest> writes, CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -814,6 +873,8 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets the current health status of the driver.</summary>
|
||||
/// <returns>The driver health information.</returns>
|
||||
public DriverHealth GetHealth() => _health;
|
||||
|
||||
/// <summary>
|
||||
@@ -821,8 +882,12 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// GC. driver-specs.md §3 flags this: operators must watch whole-process RSS for the
|
||||
/// full picture, and <see cref="ReinitializeAsync"/> is the Tier-B remediation.
|
||||
/// </summary>
|
||||
/// <returns>The memory footprint in bytes.</returns>
|
||||
public long GetMemoryFootprint() => 0;
|
||||
|
||||
/// <summary>Flushes optional caches to free memory.</summary>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A completed task.</returns>
|
||||
public Task FlushOptionalCachesAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_templateCache.Clear();
|
||||
@@ -838,6 +903,9 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// controller-discovered tags under a <c>Discovered/</c> sub-folder. System / module /
|
||||
/// routine / task tags are hidden via <see cref="AbCipSystemTagFilter"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The address space builder to populate with discovered tags.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the operation.</param>
|
||||
/// <returns>A task representing the asynchronous discovery.</returns>
|
||||
public async Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken cancellationToken)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(builder);
|
||||
@@ -934,11 +1002,16 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
internal int DeviceCount => _devices.Count;
|
||||
|
||||
/// <summary>Looked-up device state for the given host address. Tests + later-PR capabilities hit this.</summary>
|
||||
/// <param name="hostAddress">The host address of the device to look up.</param>
|
||||
/// <returns>The device state if found; null otherwise.</returns>
|
||||
internal DeviceState? GetDeviceState(string hostAddress) =>
|
||||
_devices.TryGetValue(hostAddress, out var s) ? s : null;
|
||||
|
||||
/// <summary>Releases all resources used by the driver.</summary>
|
||||
public void Dispose() => DisposeAsync().AsTask().GetAwaiter().GetResult();
|
||||
|
||||
/// <summary>Asynchronously releases all resources used by the driver.</summary>
|
||||
/// <returns>A value task representing the asynchronous disposal.</returns>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await ShutdownAsync(CancellationToken.None).ConfigureAwait(false);
|
||||
@@ -956,14 +1029,22 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
AbCipDeviceOptions options,
|
||||
AbCipPlcFamilyProfile profile)
|
||||
{
|
||||
/// <summary>Gets the parsed host address for this device.</summary>
|
||||
public AbCipHostAddress ParsedAddress { get; } = parsedAddress;
|
||||
/// <summary>Gets the configuration options for this device.</summary>
|
||||
public AbCipDeviceOptions Options { get; } = options;
|
||||
/// <summary>Gets the PLC family profile for this device.</summary>
|
||||
public AbCipPlcFamilyProfile Profile { get; } = profile;
|
||||
|
||||
/// <summary>Gets the lock object used for probe synchronization.</summary>
|
||||
public object ProbeLock { get; } = new();
|
||||
/// <summary>Gets or sets the current host state of this device.</summary>
|
||||
public HostState HostState { get; set; } = HostState.Unknown;
|
||||
/// <summary>Gets or sets the UTC timestamp when the host state was last changed.</summary>
|
||||
public DateTime HostStateChangedUtc { get; set; } = DateTime.UtcNow;
|
||||
/// <summary>Gets or sets the cancellation token source for the probe loop.</summary>
|
||||
public CancellationTokenSource? ProbeCts { get; set; }
|
||||
/// <summary>Gets or sets whether the probe has been initialized.</summary>
|
||||
public bool ProbeInitialized { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -996,6 +1077,9 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
|
||||
private readonly System.Collections.Concurrent.ConcurrentDictionary<string, SemaphoreSlim> _rmwLocks = new();
|
||||
|
||||
/// <summary>Gets or creates a semaphore for coordinating RMW (read-modify-write) operations on a parent tag.</summary>
|
||||
/// <param name="parentTagName">The name of the parent tag.</param>
|
||||
/// <returns>A semaphore for coordinating RMW operations.</returns>
|
||||
public SemaphoreSlim GetRmwLock(string parentTagName) =>
|
||||
_rmwLocks.GetOrAdd(parentTagName, _ => new SemaphoreSlim(1, 1));
|
||||
|
||||
@@ -1006,6 +1090,9 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// <see cref="AbCipDeviceOptions.ConnectionSize"/>) with the family profile defaults
|
||||
/// so the wire layer sees one place that resolves both.
|
||||
/// </summary>
|
||||
/// <param name="tagName">The name of the tag to create parameters for.</param>
|
||||
/// <param name="timeout">The timeout for tag operations.</param>
|
||||
/// <returns>The computed tag creation parameters.</returns>
|
||||
public AbCipTagCreateParams BuildCreateParams(string tagName, TimeSpan timeout) => new(
|
||||
Gateway: ParsedAddress.Gateway,
|
||||
Port: ParsedAddress.Port,
|
||||
@@ -1016,6 +1103,7 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
AllowPacking: Options.AllowPacking ?? Profile.SupportsRequestPacking,
|
||||
ConnectionSize: Options.ConnectionSize ?? Profile.DefaultConnectionSize);
|
||||
|
||||
/// <summary>Disposes all runtime tag handles and clears the caches.</summary>
|
||||
public void DisposeHandles()
|
||||
{
|
||||
foreach (var r in Runtimes.Values) r.Dispose();
|
||||
|
||||
Reference in New Issue
Block a user