diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.CLI/CommandBase.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.CLI/CommandBase.cs
index 7aca25ff..e2f3f788 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.CLI/CommandBase.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.CLI/CommandBase.cs
@@ -67,11 +67,13 @@ public abstract class CommandBase : ICommand
/// Executes the command-specific workflow against the configured OPC UA endpoint.
///
/// The CLI console used for output and cancellation handling.
+ /// A value task that represents the asynchronous command execution.
public abstract ValueTask ExecuteAsync(IConsole console);
///
/// Creates a from the common command options.
///
+ /// A populated from the current command option values.
protected ConnectionSettings CreateConnectionSettings()
{
var securityMode = SecurityModeMapper.FromString(Security);
@@ -97,6 +99,7 @@ public abstract class CommandBase : ICommand
/// and returns both the service and the connection info.
///
/// The cancellation token that aborts connection setup for the command.
+ /// A tuple of the connected and the resulting .
protected async Task<(IOpcUaClientService Service, ConnectionInfo Info)> CreateServiceAndConnectAsync(
CancellationToken ct)
{
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/DefaultApplicationConfigurationFactory.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/DefaultApplicationConfigurationFactory.cs
index 18e683a7..3165f322 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/DefaultApplicationConfigurationFactory.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/DefaultApplicationConfigurationFactory.cs
@@ -12,9 +12,7 @@ internal sealed class DefaultApplicationConfigurationFactory : IApplicationConfi
{
private static readonly ILogger Logger = Log.ForContext();
- /// Creates an OPC UA application configuration from the provided connection settings.
- /// The connection settings to use.
- /// Token to cancel the operation.
+ ///
public async Task CreateAsync(ConnectionSettings settings, CancellationToken ct)
{
// Resolve the canonical PKI path lazily on first use so constructing a
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/DefaultEndpointDiscovery.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/DefaultEndpointDiscovery.cs
index a8719460..687fbd63 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/DefaultEndpointDiscovery.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/DefaultEndpointDiscovery.cs
@@ -11,10 +11,7 @@ internal sealed class DefaultEndpointDiscovery : IEndpointDiscovery
{
private static readonly ILogger Logger = Log.ForContext();
- /// Selects an OPC UA endpoint matching the requested security mode.
- /// The application configuration.
- /// The endpoint URL to query.
- /// The requested message security mode.
+ ///
public EndpointDescription SelectEndpoint(ApplicationConfiguration config, string endpointUrl,
MessageSecurityMode requestedMode)
{
@@ -53,6 +50,7 @@ internal static class EndpointSelector
/// Thrown when no endpoint matches ; the message lists the
/// security mode + policy combinations the server returned so operators can diagnose mismatches.
///
+ /// The best matching with its URL rewritten to the requested host.
public static EndpointDescription SelectBest(
IEnumerable allEndpoints,
string endpointUrl,
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/IApplicationConfigurationFactory.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/IApplicationConfigurationFactory.cs
index 29d8ae30..0a350cda 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/IApplicationConfigurationFactory.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/IApplicationConfigurationFactory.cs
@@ -13,5 +13,6 @@ internal interface IApplicationConfigurationFactory
///
/// The connection settings to configure.
/// Cancellation token for the operation.
+ /// A task that resolves to the validated .
Task CreateAsync(ConnectionSettings settings, CancellationToken ct = default);
}
\ No newline at end of file
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/IEndpointDiscovery.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/IEndpointDiscovery.cs
index 4f802729..816c3c18 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/IEndpointDiscovery.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/IEndpointDiscovery.cs
@@ -14,6 +14,7 @@ internal interface IEndpointDiscovery
/// The OPC UA application configuration.
/// The endpoint URL to discover.
/// The requested message security mode.
+ /// The best matching endpoint description for the requested security mode.
EndpointDescription SelectEndpoint(ApplicationConfiguration config, string endpointUrl,
MessageSecurityMode requestedMode);
}
\ No newline at end of file
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/ISessionAdapter.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/ISessionAdapter.cs
index d19a285c..1f9a84b7 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/ISessionAdapter.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/ISessionAdapter.cs
@@ -58,6 +58,7 @@ internal interface ISessionAdapter : IDisposable
///
/// The node whose current runtime value should be read.
/// The cancellation token that aborts the server read if the client cancels the request.
+ /// A task that resolves to the current for the node.
Task ReadValueAsync(NodeId nodeId, CancellationToken ct = default);
///
@@ -66,6 +67,7 @@ internal interface ISessionAdapter : IDisposable
/// The node whose value should be updated.
/// The typed OPC UA data value to write to the server.
/// The cancellation token that aborts the write if the client cancels the request.
+ /// A task that resolves to the OPC UA for the write operation.
Task WriteValueAsync(NodeId nodeId, DataValue value, CancellationToken ct = default);
///
@@ -75,6 +77,7 @@ internal interface ISessionAdapter : IDisposable
/// The starting node for the hierarchical browse.
/// The node classes that should be returned to the caller.
/// The cancellation token that aborts the browse request.
+ /// A task that resolves to a tuple of an optional continuation point and the returned references.
Task<(byte[]? ContinuationPoint, ReferenceDescriptionCollection References)> BrowseAsync(
NodeId nodeId, uint nodeClassMask = 0, CancellationToken ct = default);
@@ -83,6 +86,7 @@ internal interface ISessionAdapter : IDisposable
///
/// The continuation token returned by a prior browse result page.
/// The cancellation token that aborts the browse-next request.
+ /// A task that resolves to a tuple of an optional next continuation point and the returned references.
Task<(byte[]? ContinuationPoint, ReferenceDescriptionCollection References)> BrowseNextAsync(
byte[] continuationPoint, CancellationToken ct = default);
@@ -91,6 +95,7 @@ internal interface ISessionAdapter : IDisposable
///
/// The node to inspect for child objects or variables.
/// The cancellation token that aborts the child lookup.
+ /// A task that resolves to if the node has at least one child; otherwise .
Task HasChildrenAsync(NodeId nodeId, CancellationToken ct = default);
///
@@ -101,6 +106,7 @@ internal interface ISessionAdapter : IDisposable
/// The inclusive end of the requested history window.
/// The maximum number of raw samples to return to the client.
/// The cancellation token that aborts the history read.
+ /// A task that resolves to the ordered list of raw historical data values.
Task> HistoryReadRawAsync(NodeId nodeId, DateTime startTime, DateTime endTime,
int maxValues, CancellationToken ct = default);
@@ -113,6 +119,7 @@ internal interface ISessionAdapter : IDisposable
/// The OPC UA aggregate function to evaluate over the history window.
/// The processing interval, in milliseconds, for each aggregate bucket.
/// The cancellation token that aborts the aggregate history read.
+ /// A task that resolves to the ordered list of processed aggregate data values.
Task> HistoryReadAggregateAsync(NodeId nodeId, DateTime startTime, DateTime endTime,
NodeId aggregateId, double intervalMs, CancellationToken ct = default);
@@ -121,6 +128,7 @@ internal interface ISessionAdapter : IDisposable
///
/// The requested publishing interval for monitored items on the new subscription.
/// The cancellation token that aborts subscription creation.
+ /// A task that resolves to the newly created .
Task CreateSubscriptionAsync(int publishingIntervalMs, CancellationToken ct = default);
///
@@ -130,11 +138,13 @@ internal interface ISessionAdapter : IDisposable
/// The method node to invoke.
/// The ordered input arguments supplied to the server method call.
/// The cancellation token that aborts the method invocation.
+ /// A task that resolves to the list of output arguments returned by the method, or if none.
Task?> CallMethodAsync(NodeId objectId, NodeId methodId, object[] inputArguments, CancellationToken ct = default);
///
/// Closes the underlying session gracefully before the adapter is disposed or replaced during failover.
///
/// The cancellation token that aborts the close request.
+ /// A task that represents the asynchronous operation.
Task CloseAsync(CancellationToken ct = default);
}
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/ISubscriptionAdapter.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/ISubscriptionAdapter.cs
index 21aeeb0c..afedf4c7 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/ISubscriptionAdapter.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/Adapters/ISubscriptionAdapter.cs
@@ -28,6 +28,7 @@ internal interface ISubscriptionAdapter : IDisposable
///
/// The client handle returned when the monitored item was created.
/// The cancellation token that aborts the monitored-item removal.
+ /// A task that represents the asynchronous operation.
Task RemoveMonitoredItemAsync(uint clientHandle, CancellationToken ct = default);
///
@@ -46,11 +47,13 @@ internal interface ISubscriptionAdapter : IDisposable
/// Requests a condition refresh for this subscription.
///
/// The cancellation token that aborts the condition refresh request.
+ /// A task that represents the asynchronous operation.
Task ConditionRefreshAsync(CancellationToken ct = default);
///
/// Removes all monitored items and deletes the subscription.
///
/// The cancellation token that aborts subscription deletion.
+ /// A task that represents the asynchronous operation.
Task DeleteAsync(CancellationToken ct = default);
}
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/ClientStoragePaths.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/ClientStoragePaths.cs
index d1309527..9efc28f8 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/ClientStoragePaths.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/ClientStoragePaths.cs
@@ -28,6 +28,7 @@ public static class ClientStoragePaths
/// one-shot legacy-folder migration before returning so callers that depend on this
/// path (PKI store, settings file) find their existing state at the canonical name.
///
+ /// The absolute path to the client's top-level folder under LocalApplicationData.
public static string GetRoot()
{
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
@@ -37,6 +38,7 @@ public static class ClientStoragePaths
}
/// Subfolder for the application's PKI store — used by both CLI + UI.
+ /// The absolute path to the PKI store subfolder.
public static string GetPkiPath() => Path.Combine(GetRoot(), "pki");
///
@@ -45,6 +47,7 @@ public static class ClientStoragePaths
/// folder existed + was moved to canonical, false when no migration was needed or
/// canonical was already present.
///
+ /// when the legacy folder was found and moved; when no migration was needed.
public static bool TryRunLegacyMigration()
{
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/IOpcUaClientService.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/IOpcUaClientService.cs
index 6990dde4..7659d27c 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/IOpcUaClientService.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/IOpcUaClientService.cs
@@ -24,12 +24,14 @@ public interface IOpcUaClientService : IDisposable
///
/// The endpoint, security, and authentication settings used to establish the session.
/// The cancellation token that aborts the connect workflow.
+ /// A describing the active session after a successful connect.
Task ConnectAsync(ConnectionSettings settings, CancellationToken ct = default);
///
/// Disconnects from the active OPC UA endpoint and tears down subscriptions owned by the client.
///
/// The cancellation token that aborts disconnect cleanup.
+ /// A task that represents the asynchronous operation.
Task DisconnectAsync(CancellationToken ct = default);
///
@@ -37,6 +39,7 @@ public interface IOpcUaClientService : IDisposable
///
/// The node whose value should be retrieved.
/// The cancellation token that aborts the read request.
+ /// The current including value, status code, and timestamps.
Task ReadValueAsync(NodeId nodeId, CancellationToken ct = default);
///
@@ -45,6 +48,7 @@ public interface IOpcUaClientService : IDisposable
/// The node whose value should be updated.
/// The raw value supplied by the CLI or UI workflow.
/// The cancellation token that aborts the write request.
+ /// The OPC UA returned by the server for the write operation.
Task WriteValueAsync(NodeId nodeId, object value, CancellationToken ct = default);
///
@@ -52,6 +56,7 @@ public interface IOpcUaClientService : IDisposable
///
/// The node to browse, or when omitted.
/// The cancellation token that aborts the browse request.
+ /// The list of child nodes discovered under the specified parent.
Task> BrowseAsync(NodeId? parentNodeId = null, CancellationToken ct = default);
///
@@ -60,6 +65,7 @@ public interface IOpcUaClientService : IDisposable
/// The node whose value changes should be monitored.
/// The monitored-item sampling and publishing interval in milliseconds.
/// The cancellation token that aborts subscription creation.
+ /// A task that represents the asynchronous operation.
Task SubscribeAsync(NodeId nodeId, int intervalMs = 1000, CancellationToken ct = default);
///
@@ -67,6 +73,7 @@ public interface IOpcUaClientService : IDisposable
///
/// The node whose live-data subscription should be removed.
/// The cancellation token that aborts the unsubscribe request.
+ /// A task that represents the asynchronous operation.
Task UnsubscribeAsync(NodeId nodeId, CancellationToken ct = default);
///
@@ -75,18 +82,21 @@ public interface IOpcUaClientService : IDisposable
/// The event source to monitor, or the server object when omitted.
/// The publishing interval in milliseconds for the alarm subscription.
/// The cancellation token that aborts alarm subscription creation.
+ /// A task that represents the asynchronous operation.
Task SubscribeAlarmsAsync(NodeId? sourceNodeId = null, int intervalMs = 1000, CancellationToken ct = default);
///
/// Removes the active alarm subscription.
///
/// The cancellation token that aborts alarm subscription cleanup.
+ /// A task that represents the asynchronous operation.
Task UnsubscribeAlarmsAsync(CancellationToken ct = default);
///
/// Requests retained alarm conditions again so a client can repopulate its alarm list after reconnecting.
///
/// The cancellation token that aborts the condition refresh request.
+ /// A task that represents the asynchronous operation.
Task RequestConditionRefreshAsync(CancellationToken ct = default);
///
@@ -111,6 +121,7 @@ public interface IOpcUaClientService : IDisposable
/// The inclusive end of the requested history range.
/// The maximum number of raw values to return.
/// The cancellation token that aborts the history read.
+ /// The raw historical samples in the requested range.
Task> HistoryReadRawAsync(NodeId nodeId, DateTime startTime, DateTime endTime,
int maxValues = 1000, CancellationToken ct = default);
@@ -123,6 +134,7 @@ public interface IOpcUaClientService : IDisposable
/// The aggregate function the operator selected for processed history.
/// The processing interval, in milliseconds, for each aggregate bucket.
/// The cancellation token that aborts the processed history request.
+ /// The processed historical samples computed by the requested aggregate.
Task> HistoryReadAggregateAsync(NodeId nodeId, DateTime startTime, DateTime endTime,
AggregateType aggregate, double intervalMs = 3600000, CancellationToken ct = default);
@@ -130,6 +142,7 @@ public interface IOpcUaClientService : IDisposable
/// Reads redundancy status data such as redundancy mode, service level, and partner endpoint URIs.
///
/// The cancellation token that aborts redundancy inspection.
+ /// A snapshot containing redundancy mode, service level, and partner endpoint URIs.
Task GetRedundancyInfoAsync(CancellationToken ct = default);
///
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/OpcUaClientService.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/OpcUaClientService.cs
index 57a6ac70..6df7eb85 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/OpcUaClientService.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.Shared/OpcUaClientService.cs
@@ -73,13 +73,13 @@ public sealed class OpcUaClientService : IOpcUaClientService
{
}
- ///
+ /// Raised when subscribed node values change.
public event EventHandler? DataChanged;
- ///
+ /// Raised when an alarm event is received from the server.
public event EventHandler? AlarmEvent;
- ///
+ /// Raised when the connection state changes.
public event EventHandler? ConnectionStateChanged;
///
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/AvaloniaUiDispatcher.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/AvaloniaUiDispatcher.cs
index 13275830..e74c0cb2 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/AvaloniaUiDispatcher.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/AvaloniaUiDispatcher.cs
@@ -7,8 +7,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.UI.Services;
///
public sealed class AvaloniaUiDispatcher : IUiDispatcher
{
- /// Posts an action to the Avalonia UI thread for execution.
- /// The action to execute on the UI thread.
+ ///
public void Post(Action action)
{
Dispatcher.UIThread.Post(action);
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/ISettingsService.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/ISettingsService.cs
index f95c56c0..90cb9516 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/ISettingsService.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/ISettingsService.cs
@@ -6,6 +6,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.UI.Services;
public interface ISettingsService
{
/// Loads user settings from persistent storage.
+ /// The persisted , or a default instance if none are saved.
UserSettings Load();
/// Saves user settings to persistent storage.
/// The settings to save.
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/JsonSettingsService.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/JsonSettingsService.cs
index 2f793cad..97764de9 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/JsonSettingsService.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/JsonSettingsService.cs
@@ -19,8 +19,7 @@ public sealed class JsonSettingsService : ISettingsService
WriteIndented = true
};
- /// Loads user settings from the settings file.
- /// The loaded user settings, or a new default instance if load fails.
+ ///
public UserSettings Load()
{
try
@@ -37,8 +36,7 @@ public sealed class JsonSettingsService : ISettingsService
}
}
- /// Saves user settings to the settings file.
- /// The user settings to save.
+ ///
public void Save(UserSettings settings)
{
try
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/SynchronousUiDispatcher.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/SynchronousUiDispatcher.cs
index 06c5f6bc..7744cc3e 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/SynchronousUiDispatcher.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/Services/SynchronousUiDispatcher.cs
@@ -6,8 +6,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.UI.Services;
///
public sealed class SynchronousUiDispatcher : IUiDispatcher
{
- /// Executes the action synchronously on the calling thread.
- /// The action to execute.
+ ///
public void Post(Action action)
{
action();
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/AlarmsViewModel.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/AlarmsViewModel.cs
index f7033901..3589793e 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/AlarmsViewModel.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/AlarmsViewModel.cs
@@ -195,6 +195,7 @@ public partial class AlarmsViewModel : ObservableObject
///
/// Returns the monitored node ID for persistence, or null if not subscribed.
///
+ /// The monitored node ID string, or null if not currently subscribed.
public string? GetAlarmSourceNodeId()
{
return IsSubscribed ? MonitoredNodeIdText : null;
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/BrowseTreeViewModel.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/BrowseTreeViewModel.cs
index 6ca20cbf..c3c60b8e 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/BrowseTreeViewModel.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/BrowseTreeViewModel.cs
@@ -30,6 +30,7 @@ public class BrowseTreeViewModel : ObservableObject
///
/// Loads root nodes by browsing with a null parent.
///
+ /// A task that represents the asynchronous operation.
public async Task LoadRootsAsync()
{
var results = await _service.BrowseAsync();
diff --git a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/SubscriptionsViewModel.cs b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/SubscriptionsViewModel.cs
index 612ed752..c21bfd8f 100644
--- a/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/SubscriptionsViewModel.cs
+++ b/src/Client/ZB.MOM.WW.OtOpcUa.Client.UI/ViewModels/SubscriptionsViewModel.cs
@@ -143,6 +143,7 @@ public partial class SubscriptionsViewModel : ObservableObject
///
/// The node ID to subscribe to from the browse tree or persisted settings.
/// The monitored-item interval, in milliseconds, for the subscription.
+ /// A task that represents the asynchronous operation.
public async Task AddSubscriptionForNodeAsync(string nodeIdStr, int intervalMs = 1000)
{
if (!IsConnected || string.IsNullOrWhiteSpace(nodeIdStr)) return;
@@ -176,6 +177,7 @@ public partial class SubscriptionsViewModel : ObservableObject
/// The root node whose variables should be subscribed recursively.
/// The node class of the starting node so variables can be subscribed immediately.
/// The monitored-item interval, in milliseconds, used for created subscriptions.
+ /// A task that represents the asynchronous operation.
public Task AddSubscriptionRecursiveAsync(string nodeIdStr, string nodeClass, int intervalMs = 1000)
{
return AddSubscriptionRecursiveAsync(nodeIdStr, nodeClass, intervalMs, maxDepth: 10, currentDepth: 0);
@@ -211,6 +213,7 @@ public partial class SubscriptionsViewModel : ObservableObject
///
/// Returns the node IDs of all active subscriptions for persistence.
///
+ /// The list of node ID strings for all currently active subscriptions.
public List GetSubscribedNodeIds()
{
return ActiveSubscriptions.Select(s => s.NodeId).ToList();
@@ -220,6 +223,7 @@ public partial class SubscriptionsViewModel : ObservableObject
/// Restores subscriptions from a saved list of node IDs.
///
/// The node IDs persisted from a prior UI session.
+ /// A task that represents the asynchronous operation.
public async Task RestoreSubscriptionsAsync(IEnumerable nodeIds)
{
foreach (var nodeId in nodeIds)
@@ -232,6 +236,7 @@ public partial class SubscriptionsViewModel : ObservableObject
///
/// The node ID the operator wants to write.
/// The raw text value entered by the operator.
+ /// A tuple of (success flag, operator-readable message) describing the outcome of the write.
public async Task<(bool Success, string Message)> ValidateAndWriteAsync(string nodeIdStr, string rawValue)
{
try
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ClusterRoleInfo.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ClusterRoleInfo.cs
index 512be105..0861220d 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ClusterRoleInfo.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ClusterRoleInfo.cs
@@ -43,20 +43,16 @@ public sealed class ClusterRoleInfo : IClusterRoleInfo, IDisposable
_subscriber = system.ActorOf(Props.Create(() => new SubscriberActor(this)), "clusterroleinfo-subscriber");
}
- /// Gets the local cluster node identifier.
+ ///
public CommonsNodeId LocalNode => _localNode;
- /// Gets the set of roles assigned to the local node.
+ ///
public IReadOnlySet LocalRoles => _localRoles;
- /// Checks if the local node has a specific role.
- /// The role name to check.
- /// True if the local node has the specified role; otherwise false.
+ ///
public bool HasRole(string role) => _localRoles.Contains(role);
- /// Gets all cluster members that have a specific role.
- /// The role name.
- /// A read-only list of node IDs with the specified role.
+ ///
public IReadOnlyList MembersWithRole(string role)
{
lock (_lock)
@@ -68,9 +64,7 @@ public sealed class ClusterRoleInfo : IClusterRoleInfo, IDisposable
}
}
- /// Gets the current leader node for a specific role.
- /// The role name.
- /// The node ID of the current role leader, or null if no leader is elected.
+ ///
public CommonsNodeId? RoleLeader(string role)
{
lock (_lock)
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/RoleParser.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/RoleParser.cs
index a2de2290..ff6a52a8 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/RoleParser.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/RoleParser.cs
@@ -9,6 +9,7 @@ public static class RoleParser
/// Parses a comma-separated string of role names into a validated array.
/// The raw role string to parse.
+ /// An array of validated, distinct, lower-cased role names; empty array when the input is null or whitespace.
public static string[] Parse(string? raw)
{
if (string.IsNullOrWhiteSpace(raw)) return Array.Empty();
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ServiceCollectionExtensions.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ServiceCollectionExtensions.cs
index e2bab992..c4c6b348 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ServiceCollectionExtensions.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Cluster/ServiceCollectionExtensions.cs
@@ -18,6 +18,7 @@ public static class ServiceCollectionExtensions
///
/// The service collection to configure.
/// The application configuration containing cluster options.
+ /// The same for chaining.
public static IServiceCollection AddOtOpcUaCluster(this IServiceCollection services, IConfiguration configuration)
{
services.AddOptions()
@@ -45,6 +46,7 @@ public static class ServiceCollectionExtensions
///
/// The Akka configuration builder to configure.
/// The service provider for resolving cluster options.
+ /// The same for chaining.
public static AkkaConfigurationBuilder WithOtOpcUaClusterBootstrap(
this AkkaConfigurationBuilder builder,
IServiceProvider serviceProvider)
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Browsing/IBrowseSession.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Browsing/IBrowseSession.cs
index a470b7e2..38326b0f 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Browsing/IBrowseSession.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Browsing/IBrowseSession.cs
@@ -16,14 +16,22 @@ public interface IBrowseSession : IAsyncDisposable
DateTime LastUsedUtc { get; }
/// Returns the top-level browse nodes.
+ /// Cancellation token for the operation.
+ /// A task that resolves to the list of top-level browse nodes.
Task> RootAsync(CancellationToken cancellationToken);
/// Returns the direct children of the node identified by
/// .
+ /// The identifier of the node whose children to expand.
+ /// Cancellation token for the operation.
+ /// A task that resolves to the list of direct child nodes.
Task> ExpandAsync(string nodeId, CancellationToken cancellationToken);
/// Returns the attributes of the node identified by .
/// Empty for drivers whose tree is uniform (OPC UA Client). Galaxy uses this to populate
/// the attribute side-panel after the user selects an object.
+ /// The identifier of the node whose attributes to retrieve.
+ /// Cancellation token for the operation.
+ /// A task that resolves to the list of attribute descriptors for the node.
Task> AttributesAsync(string nodeId, CancellationToken cancellationToken);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Browsing/IDriverBrowser.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Browsing/IDriverBrowser.cs
index 80f80375..44a396f1 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Browsing/IDriverBrowser.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Browsing/IDriverBrowser.cs
@@ -15,5 +15,6 @@ public interface IDriverBrowser
/// Driver options serialized as JSON; same shape the runtime
/// driver would consume.
/// Cancellation for the connect phase only.
+ /// A task containing the opened browse session.
Task OpenAsync(string configJson, CancellationToken cancellationToken);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Engines/IAlarmActorStateStore.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Engines/IAlarmActorStateStore.cs
index 56b195a4..3528d989 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Engines/IAlarmActorStateStore.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Engines/IAlarmActorStateStore.cs
@@ -18,6 +18,7 @@ public interface IAlarmActorStateStore
/// Saves the alarm actor state snapshot.
/// The state snapshot to persist.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
Task SaveAsync(AlarmActorStateSnapshot snapshot, CancellationToken ct);
}
@@ -41,14 +42,10 @@ public sealed class NullAlarmActorStateStore : IAlarmActorStateStore
{
public static readonly NullAlarmActorStateStore Instance = new();
private NullAlarmActorStateStore() { }
- /// Always returns null, indicating no persisted state.
- /// The alarm identifier (unused).
- /// Cancellation token (unused).
+ ///
public Task LoadAsync(string alarmId, CancellationToken ct) =>
Task.FromResult(null);
- /// Completes immediately without persisting anything.
- /// The state snapshot (ignored).
- /// Cancellation token (unused).
+ ///
public Task SaveAsync(AlarmActorStateSnapshot snapshot, CancellationToken ct) =>
Task.CompletedTask;
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Engines/IVirtualTagEvaluator.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Engines/IVirtualTagEvaluator.cs
index 023b48cf..78d5ff4a 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Engines/IVirtualTagEvaluator.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Engines/IVirtualTagEvaluator.cs
@@ -43,11 +43,7 @@ public sealed class NullVirtualTagEvaluator : IVirtualTagEvaluator
{
public static readonly NullVirtualTagEvaluator Instance = new();
private NullVirtualTagEvaluator() { }
- /// Returns for every evaluation.
- /// The virtual tag identifier (ignored).
- /// The expression string (ignored).
- /// The variable dependencies (ignored).
- /// Always returns .
+ ///
public VirtualTagEvalResult Evaluate(string virtualTagId, string expression, IReadOnlyDictionary dependencies)
=> VirtualTagEvalResult.NoChange;
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Interfaces/IAdminOperationsClient.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Interfaces/IAdminOperationsClient.cs
index be992f84..5ce41bb8 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Interfaces/IAdminOperationsClient.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Interfaces/IAdminOperationsClient.cs
@@ -23,5 +23,6 @@ public interface IAdminOperationsClient
/// Expected reply type.
/// The message to send.
/// Cancellation token (caller-controlled timeout).
+ /// A task that resolves to the reply of type .
Task AskAsync(object message, CancellationToken ct);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Interfaces/IFleetDiagnosticsClient.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Interfaces/IFleetDiagnosticsClient.cs
index 262cf795..db6fda4e 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Interfaces/IFleetDiagnosticsClient.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Interfaces/IFleetDiagnosticsClient.cs
@@ -11,5 +11,6 @@ public interface IFleetDiagnosticsClient
/// Gets diagnostics for the specified node.
/// The node ID to retrieve diagnostics for.
/// The cancellation token.
+ /// A task that resolves to the diagnostics snapshot for the specified node.
Task GetDiagnosticsAsync(NodeId nodeId, CancellationToken ct);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Observability/OtOpcUaTelemetry.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Observability/OtOpcUaTelemetry.cs
index 1a284860..fa5a2552 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Observability/OtOpcUaTelemetry.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Observability/OtOpcUaTelemetry.cs
@@ -69,6 +69,7 @@ public static class OtOpcUaTelemetry
/// null when no listener is attached so the call site stays cheap on undecorated builds.
///
/// The deployment identifier to tag the span with.
+ /// The started , or null when no listener is attached.
public static Activity? StartDeployApplySpan(string deploymentId)
{
var activity = ActivitySource.StartActivity("otopcua.deploy.apply", ActivityKind.Internal);
@@ -77,6 +78,7 @@ public static class OtOpcUaTelemetry
}
/// Span wrapping a full OPC UA address-space rebuild (Phase7 plan → apply).
+ /// The started , or null when no listener is attached.
public static Activity? StartAddressSpaceRebuildSpan()
=> ActivitySource.StartActivity("otopcua.opcua.address_space_rebuild", ActivityKind.Internal);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredAddressSpaceSink.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredAddressSpaceSink.cs
index 3bb7e934..6f3ecea8 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredAddressSpaceSink.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredAddressSpaceSink.cs
@@ -22,37 +22,22 @@ public sealed class DeferredAddressSpaceSink : IOpcUaAddressSpaceSink
public void SetSink(IOpcUaAddressSpaceSink? sink) =>
_inner = sink ?? NullOpcUaAddressSpaceSink.Instance;
- /// Writes a value to the OPC UA address space through the inner sink.
- /// The node ID of the variable.
- /// The value to write.
- /// The OPC UA quality value.
- /// The source timestamp in UTC.
+ ///
public void WriteValue(string nodeId, object? value, OpcUaQuality quality, DateTime sourceTimestampUtc)
=> _inner.WriteValue(nodeId, value, quality, sourceTimestampUtc);
- /// Writes an alarm state through the inner sink.
- /// The node ID of the alarm condition.
- /// Whether the alarm is active.
- /// Whether the alarm has been acknowledged.
- /// The source timestamp in UTC.
+ ///
public void WriteAlarmState(string alarmNodeId, bool active, bool acknowledged, DateTime sourceTimestampUtc)
=> _inner.WriteAlarmState(alarmNodeId, active, acknowledged, sourceTimestampUtc);
- /// Ensures a folder exists in the address space through the inner sink.
- /// The node ID of the folder.
- /// The node ID of the parent folder, or null for root.
- /// The display name of the folder.
+ ///
public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName)
=> _inner.EnsureFolder(folderNodeId, parentNodeId, displayName);
- /// Ensures a variable exists in the address space through the inner sink.
- /// The node ID of the variable.
- /// The node ID of the parent folder, or null for root.
- /// The display name of the variable.
- /// The OPC UA data type of the variable.
+ ///
public void EnsureVariable(string variableNodeId, string? parentFolderNodeId, string displayName, string dataType)
=> _inner.EnsureVariable(variableNodeId, parentFolderNodeId, displayName, dataType);
- /// Rebuilds the address space through the inner sink.
+ ///
public void RebuildAddressSpace() => _inner.RebuildAddressSpace();
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredServiceLevelPublisher.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredServiceLevelPublisher.cs
index eb227979..f567d9ec 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredServiceLevelPublisher.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/OpcUa/DeferredServiceLevelPublisher.cs
@@ -16,7 +16,6 @@ public sealed class DeferredServiceLevelPublisher : IServiceLevelPublisher
public void SetInner(IServiceLevelPublisher? inner) =>
_inner = inner ?? NullServiceLevelPublisher.Instance;
- /// Publishes a service level value to the inner publisher.
- /// The service level to publish.
+ ///
public void Publish(byte serviceLevel) => _inner.Publish(serviceLevel);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/CorrelationId.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/CorrelationId.cs
index fbf9dc06..6cc827a1 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/CorrelationId.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Commons/Types/CorrelationId.cs
@@ -3,15 +3,18 @@ namespace ZB.MOM.WW.OtOpcUa.Commons.Types;
public readonly record struct CorrelationId(Guid Value)
{
/// Creates a new CorrelationId with a randomly generated GUID.
+ /// A new backed by a random GUID.
public static CorrelationId NewId() => new(Guid.NewGuid());
///
public override string ToString() => Value.ToString("N");
/// Parses a lowercase hex string without hyphens into a CorrelationId.
/// The string to parse.
+ /// A parsed from the supplied string.
public static CorrelationId Parse(string s) => new(Guid.ParseExact(s, "N"));
/// Attempts to parse a lowercase hex string without hyphens into a CorrelationId.
/// The string to parse, or null.
/// The resulting CorrelationId if parsing succeeds.
+ /// if parsing succeeded; otherwise .
public static bool TryParse(string? s, out CorrelationId id)
{
if (Guid.TryParseExact(s, "N", out var g)) { id = new CorrelationId(g); return true; }
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/LocalCache/ILocalConfigCache.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/LocalCache/ILocalConfigCache.cs
index fc92d9ec..c1618321 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/LocalCache/ILocalConfigCache.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/LocalCache/ILocalConfigCache.cs
@@ -21,10 +21,12 @@ public interface ILocalConfigCache
/// Stores a generation snapshot in the local cache.
/// The generation snapshot to store.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
Task PutAsync(GenerationSnapshot snapshot, CancellationToken ct = default);
/// Removes old generations, keeping only the most recent N.
/// The cluster identifier.
/// The number of latest generations to keep.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
Task PruneOldGenerationsAsync(string clusterId, int keepLatest = 10, CancellationToken ct = default);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/LocalCache/LiteDbConfigCache.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/LocalCache/LiteDbConfigCache.cs
index 39e5dfb4..12deb1eb 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/LocalCache/LiteDbConfigCache.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/LocalCache/LiteDbConfigCache.cs
@@ -45,9 +45,7 @@ public sealed class LiteDbConfigCache : ILocalConfigCache, IDisposable
}
}
- /// Gets the most recent snapshot for the specified cluster.
- /// The cluster ID.
- /// Cancellation token.
+ ///
public Task GetMostRecentAsync(string clusterId, CancellationToken ct = default)
{
ct.ThrowIfCancellationRequested();
@@ -58,9 +56,7 @@ public sealed class LiteDbConfigCache : ILocalConfigCache, IDisposable
return Task.FromResult(snapshot);
}
- /// Stores a snapshot in the cache.
- /// The snapshot to store.
- /// Cancellation token.
+ ///
public async Task PutAsync(GenerationSnapshot snapshot, CancellationToken ct = default)
{
ct.ThrowIfCancellationRequested();
@@ -89,10 +85,7 @@ public sealed class LiteDbConfigCache : ILocalConfigCache, IDisposable
}
}
- /// Removes old generation snapshots, keeping only the latest ones.
- /// The cluster ID.
- /// Number of latest generations to keep.
- /// Cancellation token.
+ ///
public Task PruneOldGenerationsAsync(string clusterId, int keepLatest = 10, CancellationToken ct = default)
{
ct.ThrowIfCancellationRequested();
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Services/ILdapGroupRoleMappingService.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Services/ILdapGroupRoleMappingService.cs
index a34f15fd..308f289f 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Services/ILdapGroupRoleMappingService.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Services/ILdapGroupRoleMappingService.cs
@@ -24,11 +24,13 @@ public interface ILdapGroupRoleMappingService
///
/// The LDAP groups to search for.
/// The cancellation token.
+ /// A task resolving to the list of mappings whose LDAP group matches any of the provided groups.
Task> GetByGroupsAsync(
IEnumerable ldapGroups, CancellationToken cancellationToken);
/// Enumerate every mapping; Admin UI listing only.
/// The cancellation token.
+ /// A task resolving to all LDAP group role mappings.
Task> ListAllAsync(CancellationToken cancellationToken);
/// Create a new grant.
@@ -39,11 +41,13 @@ public interface ILdapGroupRoleMappingService
///
/// The LDAP group role mapping to create.
/// The cancellation token.
+ /// A task resolving to the newly created with any DB-assigned values populated.
Task CreateAsync(LdapGroupRoleMapping row, CancellationToken cancellationToken);
/// Delete a mapping by its surrogate key.
/// The unique identifier of the mapping to delete.
/// The cancellation token.
+ /// A task that represents the asynchronous delete operation.
Task DeleteAsync(Guid id, CancellationToken cancellationToken);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Services/LdapGroupRoleMappingService.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Services/LdapGroupRoleMappingService.cs
index 283fadbc..c79809a4 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Services/LdapGroupRoleMappingService.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Services/LdapGroupRoleMappingService.cs
@@ -10,10 +10,7 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Services;
///
public sealed class LdapGroupRoleMappingService(OtOpcUaConfigDbContext db) : ILdapGroupRoleMappingService
{
- /// Gets LDAP group role mappings for the specified groups.
- /// The LDAP group names to query.
- /// The cancellation token.
- /// The matching role mappings.
+ ///
public async Task> GetByGroupsAsync(
IEnumerable ldapGroups, CancellationToken cancellationToken)
{
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs
index 718485b8..19f4487c 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs
@@ -21,6 +21,7 @@ public static class DraftValidator
/// Validates a draft snapshot and returns all validation errors found in a single pass.
///
/// The draft snapshot to validate.
+ /// A read-only list of all validation errors found; empty if the draft is valid.
public static IReadOnlyList Validate(DraftSnapshot draft)
{
var errors = new List();
@@ -147,6 +148,7 @@ public static class DraftValidator
/// Decision #125: EquipmentId = 'EQ-' + lowercase first 12 hex chars of the UUID.
/// The equipment UUID to derive the ID from.
+ /// The derived equipment ID string in the form EQ-xxxxxxxxxxxx.
public static string DeriveEquipmentId(Guid uuid) =>
"EQ-" + uuid.ToString("N")[..12].ToLowerInvariant();
@@ -203,6 +205,7 @@ public static class DraftValidator
///
/// The server cluster to validate.
/// The cluster nodes to validate against the cluster configuration.
+ /// A read-only list of all validation errors found; empty if the topology is valid.
public static IReadOnlyList ValidateClusterTopology(
ServerCluster cluster,
IReadOnlyList clusterNodes)
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeRegistry.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeRegistry.cs
index aa60242d..6c792556 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeRegistry.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverTypeRegistry.cs
@@ -55,6 +55,7 @@ public sealed class DriverTypeRegistry
/// Look up a driver type by name. Throws if unknown.
/// The driver type name to look up.
+ /// The registered for the specified type name.
public DriverTypeMetadata Get(string driverType)
{
ArgumentException.ThrowIfNullOrWhiteSpace(driverType);
@@ -69,6 +70,7 @@ public sealed class DriverTypeRegistry
/// Try to look up a driver type by name. Returns null if unknown (no exception).
/// The driver type name to look up.
+ /// The matching , or null if not registered.
public DriverTypeMetadata? TryGet(string driverType)
{
ArgumentException.ThrowIfNullOrWhiteSpace(driverType);
@@ -76,6 +78,7 @@ public sealed class DriverTypeRegistry
}
/// Snapshot of all registered driver types.
+ /// A read-only collection of all currently registered driver type metadata entries.
public IReadOnlyCollection All() => _types.Values.ToList();
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/Historian/IHistorianDataSource.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/Historian/IHistorianDataSource.cs
index 0f234500..d6895225 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/Historian/IHistorianDataSource.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/Historian/IHistorianDataSource.cs
@@ -28,6 +28,7 @@ public interface IHistorianDataSource : IDisposable
/// The end of the time range in UTC.
/// The maximum number of values to return per node.
/// A cancellation token that can be used to cancel the operation.
+ /// A task resolving to a containing the raw samples.
Task ReadRawAsync(
string fullReference,
DateTime startUtc,
@@ -46,6 +47,7 @@ public interface IHistorianDataSource : IDisposable
/// The interval for bucketing samples.
/// The aggregation function to apply to each bucket.
/// A cancellation token that can be used to cancel the operation.
+ /// A task resolving to a containing the processed interval samples.
Task ReadProcessedAsync(
string fullReference,
DateTime startUtc,
@@ -63,6 +65,7 @@ public interface IHistorianDataSource : IDisposable
/// The full reference of the tag to read.
/// The list of timestamps to read values at.
/// A cancellation token that can be used to cancel the operation.
+ /// A task resolving to a with one sample per requested timestamp.
Task ReadAtTimeAsync(
string fullReference,
IReadOnlyList timestampsUtc,
@@ -93,6 +96,7 @@ public interface IHistorianDataSource : IDisposable
/// The end of the time range in UTC.
/// The maximum number of events to return, or a non-positive value to use the default backend cap.
/// A cancellation token that can be used to cancel the operation.
+ /// A task resolving to a containing historical alarm and event records.
Task ReadEventsAsync(
string? sourceName,
DateTime startUtc,
@@ -104,5 +108,6 @@ public interface IHistorianDataSource : IDisposable
/// Point-in-time health snapshot for diagnostics and dashboards. Pure
/// observation; never blocks on backend I/O.
///
+ /// The current for this data source.
HistorianHealthSnapshot GetHealthSnapshot();
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IAddressSpaceBuilder.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IAddressSpaceBuilder.cs
index 85118c95..33e6183f 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IAddressSpaceBuilder.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IAddressSpaceBuilder.cs
@@ -18,6 +18,7 @@ public interface IAddressSpaceBuilder
///
/// OPC UA browse name (the segment of the path under the parent).
/// Human-readable display name. May equal .
+ /// A child builder scoped to inside this folder.
IAddressSpaceBuilder Folder(string browseName, string displayName);
///
@@ -27,6 +28,7 @@ public interface IAddressSpaceBuilder
/// OPC UA browse name (the segment of the path under the parent folder).
/// Human-readable display name. May equal .
/// Driver-side metadata for the variable.
+ /// An opaque handle for the registered variable.
IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo attributeInfo);
///
@@ -56,6 +58,7 @@ public interface IVariableHandle
/// Acknowledge, Deactivate).
///
/// The alarm condition information.
+ /// A sink that receives alarm lifecycle transitions for this condition.
IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IAlarmSource.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IAlarmSource.cs
index fa66e5a4..1bcbf0d5 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IAlarmSource.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IAlarmSource.cs
@@ -13,6 +13,7 @@ public interface IAlarmSource
///
/// The driver node IDs to subscribe to.
/// Cancellation token for the operation.
+ /// A task that resolves to an opaque for the new subscription.
Task SubscribeAlarmsAsync(
IReadOnlyList sourceNodeIds,
CancellationToken cancellationToken);
@@ -20,11 +21,13 @@ public interface IAlarmSource
/// Cancel an alarm subscription returned by .
/// The subscription handle returned from .
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken);
/// Acknowledge one or more active alarms by source node ID + condition ID.
/// The batch of alarm acknowledgement requests.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
Task AcknowledgeAsync(
IReadOnlyList acknowledgements,
CancellationToken cancellationToken);
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriver.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriver.cs
index 9e07ee25..646a22b9 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriver.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriver.cs
@@ -23,6 +23,7 @@ public interface IDriver
/// Initialize the driver from its DriverConfig JSON; open connections; prepare for first use.
/// The driver configuration as JSON.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken);
///
@@ -37,13 +38,16 @@ public interface IDriver
///
/// The driver configuration as JSON.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken);
/// Stop the driver, close connections, release resources. Called on shutdown or driver removal.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
Task ShutdownAsync(CancellationToken cancellationToken);
/// Current health snapshot, polled by Core for the status dashboard and ServiceLevel.
+ /// The current driver health snapshot.
DriverHealth GetHealth();
///
@@ -56,6 +60,7 @@ public interface IDriver
/// allocation tracking". Tier C drivers (process-isolated) report through the same
/// interface but the cache-flush is internal to their host.
///
+ /// The approximate driver-attributable memory footprint in bytes.
long GetMemoryFootprint();
///
@@ -63,5 +68,6 @@ public interface IDriver
/// Required-for-correctness state must NOT be flushed.
///
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
Task FlushOptionalCachesAsync(CancellationToken cancellationToken);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverFactory.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverFactory.cs
index ab154e30..e27fd6a9 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverFactory.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverFactory.cs
@@ -34,12 +34,8 @@ public sealed class NullDriverFactory : IDriverFactory
public static readonly NullDriverFactory Instance = new();
private NullDriverFactory() { }
- /// Creates a driver (always returns null in this null implementation).
- /// The driver type name.
- /// The driver instance identifier.
- /// The driver configuration as a JSON string.
- /// Always returns null.
+ ///
public IDriver? TryCreate(string driverType, string driverInstanceId, string driverConfigJson) => null;
- /// Gets the collection of supported driver types (empty in this null implementation).
+ ///
public IReadOnlyCollection SupportedTypes { get; } = Array.Empty();
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverHealthPublisher.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverHealthPublisher.cs
index fa2516db..bfe43c4d 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverHealthPublisher.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverHealthPublisher.cs
@@ -11,6 +11,10 @@ public interface IDriverHealthPublisher
/// Publishes a health snapshot for one driver instance. Implementations must be
/// non-blocking and tolerant of being called from any thread.
///
+ /// The cluster identifier the driver instance belongs to.
+ /// The unique identifier of the driver instance.
+ /// The current health state of the driver instance.
+ /// Number of errors recorded in the past 5 minutes.
void Publish(
string clusterId,
string driverInstanceId,
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverProbe.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverProbe.cs
index 2043f3cf..5815ae5c 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverProbe.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverProbe.cs
@@ -17,6 +17,10 @@ public interface IDriverProbe
/// timeout cancellation. Never throw on connection failure; instead return a result
/// with Ok = false + a message.
///
+ /// Driver configuration JSON; same shape the runtime driver consumes.
+ /// Maximum duration for the probe attempt.
+ /// Cancellation token for the probe operation.
+ /// A task containing the probe result with success status and optional latency.
Task ProbeAsync(string configJson, TimeSpan timeout, CancellationToken ct);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverSupervisor.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverSupervisor.cs
index 0e072712..33e5b160 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverSupervisor.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IDriverSupervisor.cs
@@ -22,5 +22,6 @@ public interface IDriverSupervisor
///
/// Human-readable reason — flows into the supervisor's logs.
/// Cancels the recycle request; an in-flight restart is not interrupted.
+ /// A task that represents the asynchronous operation.
Task RecycleAsync(string reason, CancellationToken cancellationToken);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IHistoryProvider.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IHistoryProvider.cs
index 70e089bd..173e3026 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IHistoryProvider.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IHistoryProvider.cs
@@ -94,6 +94,7 @@ public interface IHistoryProvider
/// HistorianDataSource). The asymmetry is intentional — Core.Abstractions-006.
///
/// Request cancellation.
+ /// A task that resolves to the historical events result for the requested window.
///
/// Default implementation throws. Only drivers with an event historian (Galaxy via the
/// Wonderware Alarm & Events log) override. Modbus / the OPC UA Client driver stay
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IHostConnectivityProbe.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IHostConnectivityProbe.cs
index 3a446b1d..e712ca9b 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IHostConnectivityProbe.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IHostConnectivityProbe.cs
@@ -16,6 +16,7 @@ public interface IHostConnectivityProbe
/// Snapshot of host-level connectivity. The Core uses this to drive Bad-quality
/// fan-out scoped to the affected host's subtree (not the whole driver namespace).
///
+ /// A snapshot list of per-host connectivity statuses.
IReadOnlyList GetHostStatuses();
/// Fired when a host transitions Running ↔ Stopped (or similar lifecycle change).
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/ITagDiscovery.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/ITagDiscovery.cs
index e66f3a9e..87b02f80 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/ITagDiscovery.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/ITagDiscovery.cs
@@ -13,5 +13,6 @@ public interface ITagDiscovery
///
/// The address space builder to stream discovered nodes into.
/// A cancellation token for the discovery operation.
+ /// A task that represents the asynchronous discovery operation.
Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken cancellationToken);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IWritable.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IWritable.cs
index 4abf60e4..75f69c3c 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IWritable.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/IWritable.cs
@@ -19,6 +19,7 @@ public interface IWritable
///
/// Pairs of full reference + value to write.
/// Cancellation token; the driver should abort the batch if cancelled.
+ /// A task that resolves to one per requested write, in the same order.
Task> WriteAsync(
IReadOnlyList writes,
CancellationToken cancellationToken);
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/PollGroupEngine.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/PollGroupEngine.cs
index f8c54378..ed526ca5 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/PollGroupEngine.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/PollGroupEngine.cs
@@ -41,6 +41,7 @@ public sealed class PollGroupEngine : IAsyncDisposable
/// Default floor for publishing intervals — matches the Modbus 100 ms cap.
public static readonly TimeSpan DefaultMinInterval = TimeSpan.FromMilliseconds(100);
+ /// Initializes a new poll-group engine with the supplied reader, change callback, interval floor, and optional error sink.
/// Driver-supplied batch reader; snapshots MUST be returned in the same
/// order as the input references.
/// Callback invoked per changed tag — the driver forwards to its own
@@ -68,6 +69,7 @@ public sealed class PollGroupEngine : IAsyncDisposable
/// Register a new polled subscription and start its background loop.
/// The list of tag references to poll.
/// The desired polling interval; will be clamped to the configured minimum.
+ /// A subscription handle that can be passed to to cancel the loop.
public ISubscriptionHandle Subscribe(IReadOnlyList fullReferences, TimeSpan publishingInterval)
{
ArgumentNullException.ThrowIfNull(fullReferences);
@@ -207,6 +209,7 @@ public sealed class PollGroupEngine : IAsyncDisposable
}
/// Cancel every active subscription and await all loop tasks. Idempotent.
+ /// A value task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
// Cancel all loops first so they can all start winding down in parallel.
@@ -253,7 +256,7 @@ public sealed class PollGroupEngine : IAsyncDisposable
private sealed record PollSubscriptionHandle(long Id) : ISubscriptionHandle
{
- /// Gets a diagnostic identifier for this subscription.
+ ///
public string DiagnosticId => $"poll-sub-{Id}";
}
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian/IAlarmHistorianSink.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian/IAlarmHistorianSink.cs
index 8fc95c86..bcb2b4a7 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian/IAlarmHistorianSink.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian/IAlarmHistorianSink.cs
@@ -26,9 +26,11 @@ public interface IAlarmHistorianSink
/// Durably enqueue the event. Returns as soon as the queue row is committed.
/// The alarm historian event to enqueue.
/// A cancellation token for async operations.
+ /// A task that represents the asynchronous enqueue operation.
Task EnqueueAsync(AlarmHistorianEvent evt, CancellationToken cancellationToken);
/// Snapshot of current queue depth + drain health.
+ /// A snapshot of the current queue depth and drain state.
HistorianSinkStatus GetStatus();
}
@@ -97,6 +99,7 @@ public interface IAlarmHistorianWriter
/// Push a batch of events to the historian. Returns one outcome per event, same order.
/// The batch of alarm historian events to write.
/// A cancellation token for async operations.
+ /// A task that resolves to one write outcome per event, in the same order as the batch.
Task> WriteBatchAsync(
IReadOnlyList batch, CancellationToken cancellationToken);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian/SqliteStoreAndForwardSink.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian/SqliteStoreAndForwardSink.cs
index f887990f..eb03013f 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian/SqliteStoreAndForwardSink.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian/SqliteStoreAndForwardSink.cs
@@ -255,6 +255,7 @@ public sealed class SqliteStoreAndForwardSink : IAlarmHistorianSink, IDisposable
///
/// The alarm historian event to enqueue.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
public async Task EnqueueAsync(AlarmHistorianEvent evt, CancellationToken cancellationToken)
{
if (evt is null) throw new ArgumentNullException(nameof(evt));
@@ -345,6 +346,7 @@ public sealed class SqliteStoreAndForwardSink : IAlarmHistorianSink, IDisposable
/// connections per tick, each paying the open + PRAGMA cost.
///
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
public async Task DrainOnceAsync(CancellationToken ct)
{
if (_disposed) return;
@@ -490,7 +492,7 @@ public sealed class SqliteStoreAndForwardSink : IAlarmHistorianSink, IDisposable
}
}
- /// Gets the current status of the historian sink including queue depth and drain state.
+ ///
public HistorianSinkStatus GetStatus()
{
// Core.AlarmHistorian-008: read the non-dead-lettered count from the in-memory
@@ -534,6 +536,7 @@ public sealed class SqliteStoreAndForwardSink : IAlarmHistorianSink, IDisposable
}
/// Operator action from Admin UI — retry every dead-lettered row. Non-cascading: they rejoin the regular queue + get a fresh backoff.
+ /// The number of rows moved back to the active queue.
public int RetryDeadLettered()
{
using var conn = OpenConnection();
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms/ScriptedAlarmEngine.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms/ScriptedAlarmEngine.cs
index 700ec0bc..8c69dc43 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms/ScriptedAlarmEngine.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms/ScriptedAlarmEngine.cs
@@ -97,6 +97,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// copy under the gate. (Core.ScriptedAlarms-013.)
///
/// The alarm identifier to look up.
+ /// The live read-cache dictionary for the alarm, or if not yet allocated.
internal IReadOnlyDictionary? TryGetScratchReadCacheForTest(string alarmId)
=> _scratchByAlarmId.TryGetValue(alarmId, out var s) ? s.ReadCache : null;
@@ -113,6 +114,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// (Core.ScriptedAlarms-013.)
///
/// The alarm identifier to look up.
+ /// The reusable for the alarm, or if not yet allocated.
internal AlarmPredicateContext? TryGetScratchContextForTest(string alarmId)
=> _scratchByAlarmId.TryGetValue(alarmId, out var s) ? s.Context : null;
private readonly ConcurrentDictionary _valueCache
@@ -175,6 +177,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
///
/// The alarm definitions to load.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
public async Task LoadAsync(IReadOnlyList definitions, CancellationToken ct)
{
if (_disposed) throw new ObjectDisposedException(nameof(ScriptedAlarmEngine));
@@ -306,10 +309,12 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// unknown alarm. Mainly used for diagnostics + the Admin UI status page.
///
/// The alarm identifier.
+ /// The current for the alarm, or if the alarm is unknown.
public AlarmConditionState? GetState(string alarmId)
=> _alarms.TryGetValue(alarmId, out var s) ? s.Condition : null;
/// Gets the current persisted state for all loaded alarms.
+ /// A snapshot collection of all current alarm condition states.
public IReadOnlyCollection GetAllStates()
=> _alarms.Values.Select(a => a.Condition).ToArray();
@@ -318,6 +323,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// The user performing the acknowledgment.
/// An optional comment to attach to the acknowledgment.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
public Task AcknowledgeAsync(string alarmId, string user, string? comment, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyAcknowledge(cur, user, comment, _clock()));
@@ -326,6 +332,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// The user performing the confirmation.
/// An optional comment to attach to the confirmation.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
public Task ConfirmAsync(string alarmId, string user, string? comment, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyConfirm(cur, user, comment, _clock()));
@@ -333,6 +340,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// The alarm identifier.
/// The user performing the shelve operation.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
public Task OneShotShelveAsync(string alarmId, string user, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyOneShotShelve(cur, user, _clock()));
@@ -341,6 +349,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// The user performing the shelve operation.
/// The UTC time at which the shelve will automatically expire.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
public Task TimedShelveAsync(string alarmId, string user, DateTime unshelveAtUtc, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyTimedShelve(cur, user, unshelveAtUtc, _clock()));
@@ -348,6 +357,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// The alarm identifier.
/// The user performing the unshelve operation.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
public Task UnshelveAsync(string alarmId, string user, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyUnshelve(cur, user, _clock()));
@@ -355,6 +365,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// The alarm identifier.
/// The user performing the enable operation.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
public Task EnableAsync(string alarmId, string user, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyEnable(cur, user, _clock()));
@@ -362,6 +373,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// The alarm identifier.
/// The user performing the disable operation.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
public Task DisableAsync(string alarmId, string user, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyDisable(cur, user, _clock()));
@@ -370,6 +382,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// The user adding the comment.
/// The comment text.
/// The cancellation token.
+ /// A task that represents the asynchronous operation.
public Task AddCommentAsync(string alarmId, string user, string text, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyAddComment(cur, user, text, _clock()));
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/DependencyExtractor.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/DependencyExtractor.cs
index 819c0651..ebbeddca 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/DependencyExtractor.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/DependencyExtractor.cs
@@ -39,6 +39,7 @@ public static class DependencyExtractor
/// paths, or a list of rejection messages if non-literal paths were used.
///
/// The script source code to analyze.
+ /// The extracted dependency paths, or rejection messages for unsupported patterns.
public static DependencyExtractionResult Extract(string scriptSource)
{
if (string.IsNullOrWhiteSpace(scriptSource))
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptContext.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptContext.cs
index 8b1d0767..e245f151 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptContext.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptContext.cs
@@ -41,6 +41,7 @@ public abstract class ScriptContext
/// right upstream tags at load time.
///
/// The literal tag path to read.
+ /// The current for the tag, including value, quality, and timestamp.
public abstract DataValueSnapshot GetTag(string path);
///
@@ -81,6 +82,7 @@ public abstract class ScriptContext
/// The current value to check.
/// The previous value to compare against.
/// The minimum difference threshold for a change to be detected.
+ /// when the absolute difference between current and previous exceeds tolerance.
public static bool Deadband(double current, double previous, double tolerance)
=> Math.Abs(current - previous) > tolerance;
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptEvaluator.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptEvaluator.cs
index de482ede..ea508ca8 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptEvaluator.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptEvaluator.cs
@@ -66,6 +66,7 @@ public sealed class ScriptEvaluator : IDisposable
/// Compiles user script source into an evaluator.
/// The user script source code to compile.
+ /// A compiled ready to invoke.
public static ScriptEvaluator Compile(string scriptSource)
{
if (scriptSource is null) throw new ArgumentNullException(nameof(scriptSource));
@@ -173,6 +174,7 @@ public sealed class ScriptEvaluator : IDisposable
/// Runs the script against an already-constructed context.
/// The script context.
/// Cancellation token for the operation.
+ /// A task that resolves to the script's return value.
public Task RunAsync(TContext context, CancellationToken ct = default)
{
if (_disposed) throw new ObjectDisposedException(nameof(ScriptEvaluator));
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptSandbox.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptSandbox.cs
index aed728d0..5cf6fbde 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptSandbox.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting/ScriptSandbox.cs
@@ -43,6 +43,7 @@ public static class ScriptSandbox
/// to resolve ctx.GetTag(...) calls.
///
/// The concrete script context type to use for compilation.
+ /// The sandbox configuration for compiling scripts with the given context type.
public static SandboxConfig Build(Type contextType)
{
if (contextType is null) throw new ArgumentNullException(nameof(contextType));
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/DependencyGraph.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/DependencyGraph.cs
index e655196e..52d7b890 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/DependencyGraph.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/DependencyGraph.cs
@@ -156,6 +156,7 @@ public sealed class DependencyGraph
/// dependencies. Throws if any cycle
/// exists. Implemented via Kahn's algorithm.
///
+ /// A list of node IDs in topological evaluation order.
public IReadOnlyList TopologicalSort()
{
// Kahn's framing: edge u -> v means "u must come before v". For dependencies,
@@ -205,6 +206,7 @@ public sealed class DependencyGraph
/// Empty list means the graph is a DAG. Useful for surfacing every cycle in one
/// rejection pass so operators see all of them, not just one at a time.
///
+ /// A list of strongly-connected components that form cycles; empty if the graph is acyclic.
public IReadOnlyList> DetectCycles()
{
// Iterative Tarjan's SCC. Avoids recursion so deep graphs don't StackOverflow.
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/ITagUpstreamSource.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/ITagUpstreamSource.cs
index b6ba7612..dec9abd1 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/ITagUpstreamSource.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/ITagUpstreamSource.cs
@@ -30,6 +30,7 @@ public interface ITagUpstreamSource
/// when the path isn't configured.
///
/// The tag path to read.
+ /// The last-known value and quality snapshot for the tag.
DataValueSnapshot ReadTag(string path);
///
@@ -40,5 +41,6 @@ public interface ITagUpstreamSource
///
/// The tag path to subscribe to.
/// The callback to invoke when the value changes.
+ /// An that cancels the subscription when disposed.
IDisposable SubscribeTag(string path, Action observer);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/VirtualTagEngine.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/VirtualTagEngine.cs
index efd330fb..4cc929f6 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/VirtualTagEngine.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/VirtualTagEngine.cs
@@ -198,6 +198,7 @@ public sealed class VirtualTagEngine : IDisposable
/// default. Also called after a config reload.
///
/// Cancellation token to stop evaluation.
+ /// A task that represents the asynchronous operation.
public async Task EvaluateAllAsync(CancellationToken ct = default)
{
EnsureLoaded();
@@ -212,6 +213,7 @@ public sealed class VirtualTagEngine : IDisposable
/// Evaluate a single tag — used by the timer trigger + test hooks.
/// Path of the virtual tag to evaluate.
/// Cancellation token to stop evaluation.
+ /// A task that represents the asynchronous operation.
public Task EvaluateOneAsync(string path, CancellationToken ct = default)
{
EnsureLoaded();
@@ -226,6 +228,7 @@ public sealed class VirtualTagEngine : IDisposable
/// evaluation result.
///
/// Path of the tag to read.
+ /// The most recently cached value and quality for the tag path.
public DataValueSnapshot Read(string path)
{
if (string.IsNullOrWhiteSpace(path))
@@ -242,6 +245,7 @@ public sealed class VirtualTagEngine : IDisposable
///
/// Path of the tag to subscribe to.
/// Callback invoked with the tag path and new value on each evaluation.
+ /// An that cancels the subscription when disposed.
public IDisposable Subscribe(string path, Action observer)
{
// Race-safe pattern paired with Unsub.Dispose: if Unsub.Dispose removed the
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/AuthorizationDecision.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/AuthorizationDecision.cs
index 7050f75c..b811aaf3 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/AuthorizationDecision.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/AuthorizationDecision.cs
@@ -19,6 +19,7 @@ public sealed record AuthorizationDecision(
public bool IsAllowed => Verdict == AuthorizationVerdict.Allow;
/// Convenience constructor for the common "no grants matched" outcome.
+ /// An with and empty provenance.
public static AuthorizationDecision NotGranted() => new(AuthorizationVerdict.NotGranted, []);
/// Allow with the list of grants that matched.
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/IPermissionEvaluator.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/IPermissionEvaluator.cs
index ea96aeba..5e8ae98c 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/IPermissionEvaluator.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/IPermissionEvaluator.cs
@@ -22,5 +22,6 @@ public interface IPermissionEvaluator
/// The user session containing resolved LDAP groups and roles.
/// The OPC UA operation being requested.
/// The node address scope being accessed.
+ /// An indicating whether the operation is allowed.
AuthorizationDecision Authorize(UserAuthorizationState session, OpcUaOperation operation, NodeScope scope);
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrie.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrie.cs
index fc82204a..bfd1a339 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrie.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrie.cs
@@ -33,6 +33,7 @@ public sealed class PermissionTrie
///
/// The node scope to match permissions for.
/// The user's LDAP group memberships.
+ /// The list of grants that apply to the given scope for any of the session's LDAP groups.
public IReadOnlyList CollectMatches(NodeScope scope, IEnumerable ldapGroups)
{
ArgumentNullException.ThrowIfNull(scope);
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrieBuilder.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrieBuilder.cs
index 3e6fd838..a9cacec1 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrieBuilder.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrieBuilder.cs
@@ -41,6 +41,7 @@ public static class PermissionTrieBuilder
/// Core-011 production hazard. The callback fires only when
/// is non-null (a null lookup is the explicit deterministic-test fallback mode).
///
+ /// An immutable for the given cluster and generation.
public static PermissionTrie Build(
string clusterId,
long generationId,
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrieCache.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrieCache.cs
index 47161e0a..f61a2bcc 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrieCache.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/PermissionTrieCache.cs
@@ -34,6 +34,7 @@ public sealed class PermissionTrieCache
/// Get the current-generation trie for a cluster; null when nothing installed.
/// The cluster identifier.
+ /// The current-generation trie, or null if nothing is installed for the cluster.
public PermissionTrie? GetTrie(string clusterId)
{
ArgumentException.ThrowIfNullOrWhiteSpace(clusterId);
@@ -43,6 +44,7 @@ public sealed class PermissionTrieCache
/// Get a specific (cluster, generation) trie; null if that pair isn't cached.
/// The cluster identifier.
/// The generation identifier.
+ /// The trie for the specified cluster and generation, or null if not cached.
public PermissionTrie? GetTrie(string clusterId, long generationId)
{
if (!_byCluster.TryGetValue(clusterId, out var entry)) return null;
@@ -51,6 +53,7 @@ public sealed class PermissionTrieCache
/// The generation id the shortcut currently serves for a cluster.
/// The cluster identifier.
+ /// The current generation ID, or null if no trie is installed for the cluster.
public long? CurrentGenerationId(string clusterId)
=> _byCluster.TryGetValue(clusterId, out var entry) ? entry.Current.GenerationId : null;
@@ -111,11 +114,13 @@ public sealed class PermissionTrieCache
/// Creates a cluster entry from a single trie.
/// The permission trie to create the entry from.
+ /// A new containing the single trie as the current generation.
public static ClusterEntry FromSingle(PermissionTrie trie) =>
new(trie, new Dictionary { [trie.GenerationId] = trie });
/// Creates a new entry with an additional trie, updating current if it's newer.
/// The new permission trie to add.
+ /// A new with the trie added and the current pointer updated if the new generation is newer.
public ClusterEntry WithAdditional(PermissionTrie trie)
{
var next = new Dictionary(Tries) { [trie.GenerationId] = trie };
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/TriePermissionEvaluator.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/TriePermissionEvaluator.cs
index a92608cc..5b43b6ed 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/TriePermissionEvaluator.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/TriePermissionEvaluator.cs
@@ -24,11 +24,7 @@ public sealed class TriePermissionEvaluator : IPermissionEvaluator
_timeProvider = timeProvider ?? TimeProvider.System;
}
- /// Authorizes an operation against the user's session and node scope.
- /// The user's authorization session.
- /// The OPC UA operation to authorize.
- /// The target node scope.
- /// An authorization decision indicating whether the operation is allowed.
+ ///
public AuthorizationDecision Authorize(UserAuthorizationState session, OpcUaOperation operation, NodeScope scope)
{
ArgumentNullException.ThrowIfNull(session);
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/UserAuthorizationState.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/UserAuthorizationState.cs
index e811109c..54331342 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/UserAuthorizationState.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Authorization/UserAuthorizationState.cs
@@ -64,6 +64,7 @@ public sealed record UserAuthorizationState
/// whenever this is true.
///
/// The current UTC time.
+ /// true when the state exceeds its maximum staleness ceiling.
public bool IsStale(DateTime utcNow) => utcNow - MembershipResolvedUtc > AuthCacheMaxStaleness;
///
@@ -72,6 +73,7 @@ public sealed record UserAuthorizationState
/// call still evaluates against the cached memberships.
///
/// The current UTC time.
+ /// true when a background refresh should be initiated but the current cached memberships are still usable.
public bool NeedsRefresh(DateTime utcNow) =>
!IsStale(utcNow) && utcNow - MembershipResolvedUtc > MembershipFreshnessInterval;
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverFactoryRegistry.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverFactoryRegistry.cs
index bbade74e..d5459fe0 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverFactoryRegistry.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverFactoryRegistry.cs
@@ -63,6 +63,7 @@ public sealed class DriverFactoryRegistry
/// missing-assembly deployment doesn't take down the whole server.
///
/// The driver type to look up.
+ /// The registered factory delegate, or if no factory was registered for the type.
public Func? TryGet(string driverType)
{
ArgumentException.ThrowIfNullOrWhiteSpace(driverType);
@@ -75,6 +76,7 @@ public sealed class DriverFactoryRegistry
/// case upstream; we don't double-surface that failure here.
///
/// The driver type to look up.
+ /// The registered , or if the type is unknown.
public DriverTier GetTier(string driverType)
{
ArgumentException.ThrowIfNullOrWhiteSpace(driverType);
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverFactoryRegistryAdapter.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverFactoryRegistryAdapter.cs
index de24430e..fd44bb96 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverFactoryRegistryAdapter.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverFactoryRegistryAdapter.cs
@@ -20,16 +20,13 @@ public sealed class DriverFactoryRegistryAdapter : IDriverFactory
_registry = registry;
}
- /// Attempts to create a driver instance by type and configuration.
- /// The driver type name.
- /// The driver instance identifier.
- /// The driver configuration as a JSON string.
+ ///
public IDriver? TryCreate(string driverType, string driverInstanceId, string driverConfigJson)
{
var factory = _registry.TryGet(driverType);
return factory?.Invoke(driverInstanceId, driverConfigJson);
}
- /// Gets the collection of supported driver type names.
+ ///
public IReadOnlyCollection SupportedTypes => _registry.RegisteredTypes;
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverHost.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverHost.cs
index 9c8dbd86..7bf283f5 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverHost.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Hosting/DriverHost.cs
@@ -21,6 +21,7 @@ public sealed class DriverHost : IAsyncDisposable
/// Gets the health status of a registered driver.
/// The driver instance identifier to query.
+ /// The driver health if the driver is registered; otherwise null.
public DriverHealth? GetHealth(string driverInstanceId)
{
lock (_lock)
@@ -33,6 +34,7 @@ public sealed class DriverHost : IAsyncDisposable
/// startup. Returns null when the driver is not registered.
///
/// The driver instance identifier to look up.
+ /// The driver instance if registered; otherwise null.
public IDriver? GetDriver(string driverInstanceId)
{
lock (_lock)
@@ -47,6 +49,7 @@ public sealed class DriverHost : IAsyncDisposable
/// The driver instance to register.
/// The configuration JSON for the driver.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
public async Task RegisterAsync(IDriver driver, string driverConfigJson, CancellationToken ct)
{
ArgumentNullException.ThrowIfNull(driver);
@@ -70,6 +73,7 @@ public sealed class DriverHost : IAsyncDisposable
/// Unregisters a driver and calls shutdown.
/// The driver instance identifier to unregister.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
public async Task UnregisterAsync(string driverInstanceId, CancellationToken ct)
{
IDriver? driver;
@@ -84,6 +88,7 @@ public sealed class DriverHost : IAsyncDisposable
}
/// Disposes the driver host and all registered drivers.
+ /// A value task that represents the asynchronous operation.
public async ValueTask DisposeAsync()
{
List snapshot;
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Observability/DriverHealthReport.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Observability/DriverHealthReport.cs
index bd4f0961..99309b9d 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Observability/DriverHealthReport.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Observability/DriverHealthReport.cs
@@ -27,6 +27,7 @@ public static class DriverHealthReport
{
/// Compute the fleet-wide readiness verdict from per-driver states.
/// The list of per-driver health snapshots to aggregate.
+ /// The fleet-wide derived from all driver states.
public static ReadinessVerdict Aggregate(IReadOnlyList drivers)
{
ArgumentNullException.ThrowIfNull(drivers);
@@ -54,6 +55,7 @@ public static class DriverHealthReport
/// return per the Stream C.1 state matrix.
///
/// The readiness verdict to map to HTTP status.
+ /// The HTTP status code (200 or 503) corresponding to the verdict.
public static int HttpStatus(ReadinessVerdict verdict) => verdict switch
{
ReadinessVerdict.Healthy => 200,
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Observability/LogContextEnricher.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Observability/LogContextEnricher.cs
index 97f34a83..7a7bb80b 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Observability/LogContextEnricher.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Observability/LogContextEnricher.cs
@@ -22,6 +22,7 @@ public static class LogContextEnricher
/// The driver type name.
/// The driver capability being invoked.
/// The correlation ID for tracing the call.
+ /// A scope that pops the pushed properties when disposed.
public static IDisposable Push(string driverInstanceId, string driverType, DriverCapability capability, string correlationId)
{
ArgumentException.ThrowIfNullOrWhiteSpace(driverInstanceId);
@@ -40,6 +41,7 @@ public static class LogContextEnricher
/// 12-hex-char slice of a GUID — long enough for log correlation, short enough to
/// scan visually.
///
+ /// A 12-character hex string suitable for log correlation.
public static string NewCorrelationId() => Guid.NewGuid().ToString("N")[..12];
private sealed class CompositeScope : IDisposable
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/EquipmentNodeWalker.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/EquipmentNodeWalker.cs
index 01da5665..6bda50e5 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/EquipmentNodeWalker.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/EquipmentNodeWalker.cs
@@ -183,6 +183,7 @@ public static class EquipmentNodeWalker
/// wants an opaque non-JSON reference.
///
/// The tag configuration JSON or string.
+ /// The value of the FullName field from the JSON, or the raw string as a fallback.
internal static string ExtractFullName(string tagConfig)
{
if (string.IsNullOrWhiteSpace(tagConfig)) return tagConfig;
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/GenericDriverNodeManager.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/GenericDriverNodeManager.cs
index 6399075d..16e36612 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/GenericDriverNodeManager.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/OpcUa/GenericDriverNodeManager.cs
@@ -49,6 +49,7 @@ public class GenericDriverNodeManager(IDriver driver) : IDisposable
///
/// The address space builder to populate.
/// The cancellation token.
+ /// A task that represents the asynchronous address space build operation.
public async Task BuildAddressSpaceAsync(IAddressSpaceBuilder builder, CancellationToken ct)
{
ArgumentNullException.ThrowIfNull(builder);
@@ -111,23 +112,15 @@ public class GenericDriverNodeManager(IDriver driver) : IDisposable
IAddressSpaceBuilder inner,
ConcurrentDictionary sinks) : IAddressSpaceBuilder
{
- /// Adds a folder to the address space.
- /// The browse name of the folder node.
- /// The display name of the folder node.
+ ///
public IAddressSpaceBuilder Folder(string browseName, string displayName)
=> new CapturingBuilder(inner.Folder(browseName, displayName), sinks);
- /// Adds a variable to the address space.
- /// The browse name of the variable node.
- /// The display name of the variable node.
- /// Metadata describing the variable's data type and properties.
+ ///
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo attributeInfo)
=> new CapturingHandle(inner.Variable(browseName, displayName, attributeInfo), sinks);
- /// Adds a property to the address space.
- /// The browse name of the property node.
- /// The OPC UA data type of the property.
- /// The initial value of the property, or null.
+ ///
public void AddProperty(string browseName, DriverDataType dataType, object? value)
=> inner.AddProperty(browseName, dataType, value);
}
@@ -136,11 +129,10 @@ public class GenericDriverNodeManager(IDriver driver) : IDisposable
IVariableHandle inner,
ConcurrentDictionary sinks) : IVariableHandle
{
- /// Gets the full reference for the variable.
+ ///
public string FullReference => inner.FullReference;
- /// Marks the variable as an alarm condition and registers its sink.
- /// Configuration for the alarm condition.
+ ///
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info)
{
var sink = inner.MarkAsAlarmCondition(info);
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/AlarmSurfaceInvoker.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/AlarmSurfaceInvoker.cs
index ba2c6014..0368945e 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/AlarmSurfaceInvoker.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/AlarmSurfaceInvoker.cs
@@ -59,6 +59,7 @@ public sealed class AlarmSurfaceInvoker
///
/// The source node IDs to subscribe to.
/// The cancellation token.
+ /// A task that resolves to one subscription handle per resolved host.
public async Task> SubscribeAsync(
IReadOnlyList sourceNodeIds,
CancellationToken cancellationToken)
@@ -89,6 +90,7 @@ public sealed class AlarmSurfaceInvoker
///
/// The subscription handle to unsubscribe.
/// The cancellation token.
+ /// A task that represents the asynchronous unsubscribe operation.
public ValueTask UnsubscribeAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(handle);
@@ -110,6 +112,7 @@ public sealed class AlarmSurfaceInvoker
///
/// The alarm acknowledgement requests.
/// The cancellation token.
+ /// A task that represents the asynchronous acknowledgement operation.
public async Task AcknowledgeAsync(
IReadOnlyList acknowledgements,
CancellationToken cancellationToken)
@@ -166,7 +169,7 @@ public sealed class AlarmSurfaceInvoker
public IAlarmSubscriptionHandle Inner { get; } = inner;
/// Gets the resolved host name.
public string Host { get; } = host;
- /// Gets the diagnostic ID from the inner handle.
+ ///
public string DiagnosticId => Inner.DiagnosticId;
}
}
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/CapabilityInvoker.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/CapabilityInvoker.cs
index 42fc65fe..0af92cb4 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/CapabilityInvoker.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/CapabilityInvoker.cs
@@ -58,6 +58,7 @@ public sealed class CapabilityInvoker
/// The host name for logging and status tracking.
/// The async function to execute.
/// Cancellation token for the operation.
+ /// The result produced by after executing through the pipeline.
public async ValueTask ExecuteAsync(
DriverCapability capability,
string hostName,
@@ -86,6 +87,7 @@ public sealed class CapabilityInvoker
/// The host name for logging and status tracking.
/// The async function to execute.
/// Cancellation token for the operation.
+ /// A value task that represents the asynchronous operation.
public async ValueTask ExecuteAsync(
DriverCapability capability,
string hostName,
@@ -121,6 +123,7 @@ public sealed class CapabilityInvoker
/// Whether the write operation is idempotent.
/// The async function to execute.
/// Cancellation token for the operation.
+ /// The result produced by after executing through the write pipeline.
public async ValueTask ExecuteWriteAsync(
string hostName,
bool isIdempotent,
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResilienceOptionsParser.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResilienceOptionsParser.cs
index 168d6677..19f983f5 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResilienceOptionsParser.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResilienceOptionsParser.cs
@@ -50,6 +50,7 @@ public static class DriverResilienceOptionsParser
/// The driver tier for default resilience options.
/// The optional JSON configuration string to parse.
/// An out parameter containing diagnostic information if parsing fails.
+ /// The effective resilience options; tier defaults when the JSON is null or malformed.
public static DriverResilienceOptions ParseOrDefaults(
DriverTier tier,
string? resilienceConfigJson,
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResiliencePipelineBuilder.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResiliencePipelineBuilder.cs
index 99fbcde7..eda8368d 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResiliencePipelineBuilder.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResiliencePipelineBuilder.cs
@@ -54,6 +54,7 @@ public sealed class DriverResiliencePipelineBuilder
///
/// Which capability surface is being called.
/// Per-driver-instance options (tier + per-capability overrides).
+ /// The cached or newly created for the given key.
public ResiliencePipeline GetOrCreate(
string driverInstanceId,
string hostName,
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResilienceStatusTracker.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResilienceStatusTracker.cs
index 1e32128a..db8b4717 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResilienceStatusTracker.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Resilience/DriverResilienceStatusTracker.cs
@@ -128,10 +128,12 @@ public sealed class DriverResilienceStatusTracker
/// Snapshot of a specific (instance, host) pair; null if no counters recorded yet.
/// The driver instance identifier.
/// The host name.
+ /// The current for the pair, or if no counters have been recorded.
public ResilienceStatusSnapshot? TryGet(string driverInstanceId, string hostName) =>
_status.TryGetValue(new StatusKey(driverInstanceId, hostName), out var snapshot) ? snapshot : null;
/// Copy of every currently-tracked (instance, host, snapshot) triple. Safe under concurrent writes.
+ /// A snapshot list of all currently tracked driver instance and host resilience states.
public IReadOnlyList<(string DriverInstanceId, string HostName, ResilienceStatusSnapshot Snapshot)> Snapshot() =>
_status.Select(kvp => (kvp.Key.DriverInstanceId, kvp.Key.HostName, kvp.Value)).ToList();
diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Stability/MemoryTracking.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Stability/MemoryTracking.cs
index 9dad09ee..977a20d8 100644
--- a/src/Core/ZB.MOM.WW.OtOpcUa.Core/Stability/MemoryTracking.cs
+++ b/src/Core/ZB.MOM.WW.OtOpcUa.Core/Stability/MemoryTracking.cs
@@ -33,6 +33,7 @@ public sealed class MemoryTracking
/// Tier-default multiplier/floor constants per decision #146.
/// The driver tier.
+ /// A tuple with the growth multiplier and the minimum floor bytes for the specified tier.
public static (int Multiplier, long FloorBytes) GetTierConstants(DriverTier tier) => tier switch
{
DriverTier.A => (Multiplier: 3, FloorBytes: 50L * 1024 * 1024),
@@ -73,6 +74,7 @@ public sealed class MemoryTracking
///
/// The current memory footprint in bytes.
/// The current UTC time.
+ /// The classifying this sample against the soft/hard thresholds.
public MemoryTrackingAction Sample(long footprintBytes, DateTime utcNow)
{
if (_phase == TrackingPhase.WarmingUp)
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli/AbCipCommandBase.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli/AbCipCommandBase.cs
index e5d9e42a..767d19be 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli/AbCipCommandBase.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli/AbCipCommandBase.cs
@@ -60,6 +60,7 @@ public abstract class AbCipCommandBase : DriverCommandBase
/// probe loop would race the operator's own reads.
///
/// The list of tag definitions to include in the options.
+ /// A fully-configured with probe and alarm projection disabled.
protected AbCipDriverOptions BuildOptions(IReadOnlyList tags) => new()
{
Devices = [new AbCipDeviceOptions(
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli/Commands/ReadCommand.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli/Commands/ReadCommand.cs
index 5bad9277..2c4e6837 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli/Commands/ReadCommand.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli/Commands/ReadCommand.cs
@@ -66,6 +66,7 @@ public sealed class ReadCommand : AbCipCommandBase
///
/// The symbolic tag path.
/// The data type.
+ /// A combined tag-name string in path:type form.
internal static string SynthesiseTagName(string tagPath, AbCipDataType type)
=> $"{tagPath}:{type}";
}
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli/Commands/ReadCommand.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli/Commands/ReadCommand.cs
index 51ac8ca1..cc293ac9 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli/Commands/ReadCommand.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli/Commands/ReadCommand.cs
@@ -58,6 +58,7 @@ public sealed class ReadCommand : AbLegacyCommandBase
/// Tag-name key the driver uses internally. Address+type is already unique.
/// The PCCC file address.
/// The data type of the address.
+ /// A combined tag name string in the form address:type.
internal static string SynthesiseTagName(string address, AbLegacyDataType type)
=> $"{address}:{type}";
}
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/SnapshotFormatter.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/SnapshotFormatter.cs
index b44ffdc5..49e2e86c 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/SnapshotFormatter.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Cli.Common/SnapshotFormatter.cs
@@ -23,6 +23,7 @@ public static class SnapshotFormatter
///
/// The tag name to include in the output.
/// The data value snapshot to format.
+ /// A multi-line string representation of the tag and its value.
public static string Format(string tagName, DataValueSnapshot snapshot)
{
ArgumentNullException.ThrowIfNull(snapshot);
@@ -42,6 +43,7 @@ public static class SnapshotFormatter
///
/// The tag name to include in the output.
/// The write result to format.
+ /// A single-line string showing the tag name and write status.
public static string FormatWrite(string tagName, WriteResult result)
{
ArgumentNullException.ThrowIfNull(result);
@@ -54,6 +56,7 @@ public static class SnapshotFormatter
///
/// The list of tag names to include as rows.
/// The list of data value snapshots to format.
+ /// An aligned table string with tag, value, status, and source-time columns.
public static string FormatTable(
IReadOnlyList tagNames, IReadOnlyList snapshots)
{
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli/Commands/ReadCommand.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli/Commands/ReadCommand.cs
index c1a92581..d2577c6d 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli/Commands/ReadCommand.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli/Commands/ReadCommand.cs
@@ -52,6 +52,7 @@ public sealed class ReadCommand : FocasCommandBase
/// Constructs a tag name from address and data type.
/// The FOCAS address.
/// The data type.
+ /// A synthesized tag name string combining the address and data type.
internal static string SynthesiseTagName(string address, FocasDataType type)
=> $"{address}:{type}";
}
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli/FocasCommandBase.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli/FocasCommandBase.cs
index cfa9957f..dc5553c8 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli/FocasCommandBase.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Cli/FocasCommandBase.cs
@@ -47,6 +47,7 @@ public abstract class FocasCommandBase : DriverCommandBase
/// as BadCommunicationError.
///
/// The tag definitions to include in the driver options.
+ /// A configured with the CNC target and the supplied tag list.
protected FocasDriverOptions BuildOptions(IReadOnlyList tags) => new()
{
Devices = [new FocasDeviceOptions(
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli/ModbusCommandBase.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli/ModbusCommandBase.cs
index d3441cc9..d8fd176c 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli/ModbusCommandBase.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli/ModbusCommandBase.cs
@@ -48,6 +48,7 @@ public abstract class ModbusCommandBase : DriverCommandBase
/// command against its own keep-alive reads.
///
/// The tag definitions to include in the options.
+ /// A configured for a one-shot CLI run.
protected ModbusDriverOptions BuildOptions(IReadOnlyList tags) => new()
{
Host = Host,
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ReadCommand.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ReadCommand.cs
index 2cda2f1e..4f3588a3 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ReadCommand.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ReadCommand.cs
@@ -61,6 +61,7 @@ public sealed class ReadCommand : S7CommandBase
/// Tag-name key used internally. Address + type is already unique.
/// The S7 address to encode in the tag name.
/// The data type to encode in the tag name.
+ /// The synthesised tag name encoding the address and type.
internal static string SynthesiseTagName(string address, S7DataType type)
=> $"{address}:{type}";
}
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/S7CommandBase.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/S7CommandBase.cs
index ecf725f5..ead55c02 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/S7CommandBase.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/S7CommandBase.cs
@@ -51,6 +51,7 @@ public abstract class S7CommandBase : DriverCommandBase
/// disabled — CLI runs are one-shot.
///
/// The tag definitions to include in the options.
+ /// An populated with the current command-line values and the supplied tags.
protected S7DriverOptions BuildOptions(IReadOnlyList tags) => new()
{
Host = Host,
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/Commands/BrowseCommand.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/Commands/BrowseCommand.cs
index fc8bec30..5805f025 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/Commands/BrowseCommand.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/Commands/BrowseCommand.cs
@@ -90,6 +90,7 @@ public sealed class BrowseCommand : TwinCATCommandBase
///
/// The source collection to filter.
/// The prefix to filter on, or null to keep everything.
+ /// A filtered list of variables whose browse names start with the given prefix.
internal static List<(string BrowseName, DriverAttributeInfo Info)> FilterByPrefix(
IReadOnlyList<(string BrowseName, DriverAttributeInfo Info)> source, string? prefix)
=> source
@@ -102,6 +103,7 @@ public sealed class BrowseCommand : TwinCATCommandBase
///
/// The number of matched items.
/// The maximum number to show, or 0 for unbounded.
+ /// The effective print limit: when unbounded, otherwise the lesser of and .
internal static int PrintLimit(int matchedCount, int max)
=> max <= 0 ? matchedCount : Math.Min(max, matchedCount);
@@ -112,6 +114,7 @@ public sealed class BrowseCommand : TwinCATCommandBase
/// authorization is enforced server-side.
///
/// The attribute info to label.
+ /// "RO" for view-only attributes; "RW" for all others.
internal static string AccessTag(DriverAttributeInfo info)
=> info.SecurityClass == SecurityClassification.ViewOnly ? "RO" : "RW";
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/Commands/WriteCommand.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/Commands/WriteCommand.cs
index 8aa3a0cc..40df4ee5 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/Commands/WriteCommand.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/Commands/WriteCommand.cs
@@ -69,6 +69,7 @@ public sealed class WriteCommand : TwinCATTagCommandBase
/// Parse --value per , invariant culture.
/// The raw string value to parse.
/// The target TwinCAT data type.
+ /// The parsed value as a boxed .NET object matching the requested data type.
internal static object ParseValue(string raw, TwinCATDataType type) => type switch
{
TwinCATDataType.Bool => ParseBool(raw),
diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/TwinCATTagCommandBase.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/TwinCATTagCommandBase.cs
index 928a05d8..23a74907 100644
--- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/TwinCATTagCommandBase.cs
+++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT.Cli/TwinCATTagCommandBase.cs
@@ -24,6 +24,7 @@ public abstract class TwinCATTagCommandBase : TwinCATCommandBase
/// native notifications toggled by .
///
/// Tag definitions for the driver.
+ /// A configured for a single-device CLI run.
protected TwinCATDriverOptions BuildOptions(IReadOnlyList tags) => new()
{
Devices = [new TwinCATDeviceOptions(
@@ -39,6 +40,7 @@ public abstract class TwinCATTagCommandBase : TwinCATCommandBase
// ---- Test hook ----
/// Test hook that exposes BuildOptions for unit testing.
/// Tag definitions for the driver.
+ /// A configured for a single-device CLI run.
internal TwinCATDriverOptions BuildOptionsForTest(IReadOnlyList tags)
=> BuildOptions(tags);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipDriver.cs
index bb53fc21..af941676 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipDriver.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipDriver.cs
@@ -130,10 +130,10 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
///
internal AbCipTemplateCache TemplateCache => _templateCache;
- /// Gets the unique identifier for this driver instance.
+ ///
public string DriverInstanceId => _driverInstanceId;
- /// Gets the driver type identifier.
+ ///
public string DriverType => "AbCip";
///
@@ -244,10 +244,7 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
return Task.CompletedTask;
}
- /// Reinitialize the driver by shutting down and reinitializing with new configuration.
- /// The new driver configuration as JSON.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous reinitialization.
+ ///
public async Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
await ShutdownAsync(cancellationToken).ConfigureAwait(false);
@@ -305,19 +302,12 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// ---- ISubscribable (polling overlay via shared engine) ----
- /// Subscribe to value changes for the specified tag references.
- /// The tag references to subscribe to.
- /// The interval at which to publish changes.
- /// Cancellation token for the operation.
- /// A handle representing the subscription.
+ ///
public Task SubscribeAsync(
IReadOnlyList fullReferences, TimeSpan publishingInterval, CancellationToken cancellationToken) =>
Task.FromResult(_poll.Subscribe(fullReferences, publishingInterval));
- /// Unsubscribe from value changes using a subscription handle.
- /// The subscription handle to unsubscribe.
- /// Cancellation token for the operation.
- /// A completed task.
+ ///
public Task UnsubscribeAsync(ISubscriptionHandle handle, CancellationToken cancellationToken)
{
_poll.Unsubscribe(handle);
@@ -349,19 +339,13 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
return _alarmProjection.SubscribeAsync(sourceNodeIds, cancellationToken);
}
- /// Unsubscribe from alarm events.
- /// The alarm subscription handle.
- /// Cancellation token for the operation.
- /// A completed task.
+ ///
public Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken) =>
_options.EnableAlarmProjection
? _alarmProjection.UnsubscribeAsync(handle, cancellationToken)
: Task.CompletedTask;
- /// Acknowledge alarms.
- /// The alarm acknowledgements to process.
- /// Cancellation token for the operation.
- /// A completed task.
+ ///
public Task AcknowledgeAsync(
IReadOnlyList acknowledgements, CancellationToken cancellationToken) =>
_options.EnableAlarmProjection
@@ -370,8 +354,7 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// ---- IHostConnectivityProbe ----
- /// Gets the connectivity status of all configured devices.
- /// A read-only list of host connectivity statuses.
+ ///
public IReadOnlyList GetHostStatuses() =>
[.. _devices.Values.Select(s => new HostConnectivityStatus(s.Options.HostAddress, s.HostState, s.HostStateChangedUtc))];
@@ -873,8 +856,7 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
}
}
- /// Gets the current health status of the driver.
- /// The driver health information.
+ ///
public DriverHealth GetHealth() => _health;
///
@@ -885,9 +867,7 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
/// The memory footprint in bytes.
public long GetMemoryFootprint() => 0;
- /// Flushes optional caches to free memory.
- /// Cancellation token for the operation.
- /// A completed task.
+ ///
public Task FlushOptionalCachesAsync(CancellationToken cancellationToken)
{
_templateCache.Clear();
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipStatusMapper.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipStatusMapper.cs
index c0fed449..601bcb1c 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipStatusMapper.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipStatusMapper.cs
@@ -48,6 +48,7 @@ public static class AbCipStatusMapper
/// Map a CIP general-status byte to an OPC UA StatusCode.
/// The CIP general-status byte value.
+ /// The corresponding OPC UA StatusCode.
public static uint MapCipGeneralStatus(byte status) => status switch
{
0x00 => Good,
@@ -72,6 +73,7 @@ public static class AbCipStatusMapper
/// operation; every other (negative) member is an error.
///
/// The libplctag status code as an integer.
+ /// The corresponding OPC UA StatusCode.
public static uint MapLibplctagStatus(int status) => MapLibplctagStatus((Status)status);
///
@@ -80,6 +82,7 @@ public static class AbCipStatusMapper
/// seam, which returns the boxed-as-int value.
///
/// The libplctag Status enum value.
+ /// The corresponding OPC UA StatusCode.
public static uint MapLibplctagStatus(Status status) => status switch
{
Status.Ok => Good,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipSystemTagFilter.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipSystemTagFilter.cs
index ed21a36b..a3fafc74 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipSystemTagFilter.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipSystemTagFilter.cs
@@ -19,6 +19,7 @@ public static class AbCipSystemTagFilter
/// always preserved case and the system-tag prefixes are uppercase by convention.
///
/// The tag name to check.
+ /// if the tag is a system tag that should be hidden; otherwise .
public static bool IsSystemTag(string tagName)
{
if (string.IsNullOrWhiteSpace(tagName)) return true;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipTagPath.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipTagPath.cs
index 2f77b24a..4d1a85d2 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipTagPath.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipTagPath.cs
@@ -24,6 +24,7 @@ public sealed record AbCipTagPath(
int? BitIndex)
{
/// Rebuild the canonical Logix tag string.
+ /// The canonical Logix tag string suitable for the libplctag name= attribute.
public string ToLibplctagName()
{
var buf = new System.Text.StringBuilder();
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipTemplateCache.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipTemplateCache.cs
index 369c45d2..2d416645 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipTemplateCache.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipTemplateCache.cs
@@ -23,6 +23,7 @@ public sealed class AbCipTemplateCache
///
/// The device host address and port.
/// The template instance ID.
+ /// The cached , or null if not yet populated.
public AbCipUdtShape? TryGet(string deviceHostAddress, uint templateInstanceId) =>
_shapes.TryGetValue((deviceHostAddress, templateInstanceId), out var shape) ? shape : null;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipUdtMemberLayout.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipUdtMemberLayout.cs
index 543d96ba..74fef203 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipUdtMemberLayout.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipUdtMemberLayout.cs
@@ -30,6 +30,7 @@ public static class AbCipUdtMemberLayout
/// if any member type is unsupported for declaration-only layout.
///
/// The list of UDT member declarations.
+ /// A dictionary mapping member name to byte offset, or if any member type is unsupported.
public static IReadOnlyDictionary? TryBuild(
IReadOnlyList members)
{
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipUdtReadPlanner.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipUdtReadPlanner.cs
index 62cef0aa..3803c8f2 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipUdtReadPlanner.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipUdtReadPlanner.cs
@@ -28,6 +28,7 @@ public static class AbCipUdtReadPlanner
/// The list of tag references to read.
/// Dictionary mapping tag names to their definitions.
/// Whether to enable UDT member grouping based on declaration order.
+ /// An partitioning requests into whole-UDT groups and per-tag fallbacks.
public static AbCipUdtReadPlan Build(
IReadOnlyList requests,
IReadOnlyDictionary tagsByName,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTagEnumerator.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTagEnumerator.cs
index 4f187b39..c79a7fd1 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTagEnumerator.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTagEnumerator.cs
@@ -15,6 +15,7 @@ public interface IAbCipTagEnumerator : IDisposable
///
/// Parameters for creating device tags.
/// Cancellation token.
+ /// An async enumerable of discovered tags.
IAsyncEnumerable EnumerateAsync(
AbCipTagCreateParams deviceParams,
CancellationToken cancellationToken);
@@ -26,6 +27,7 @@ public interface IAbCipTagEnumeratorFactory
///
/// Creates a new tag enumerator instance.
///
+ /// A new instance.
IAbCipTagEnumerator Create();
}
@@ -59,6 +61,7 @@ internal sealed class EmptyAbCipTagEnumerator : IAbCipTagEnumerator
///
/// Parameters for creating device tags.
/// Cancellation token.
+ /// An empty async enumerable of discovered tags.
public async IAsyncEnumerable EnumerateAsync(
AbCipTagCreateParams deviceParams,
[System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken)
@@ -79,5 +82,6 @@ internal sealed class EmptyAbCipTagEnumeratorFactory : IAbCipTagEnumeratorFactor
///
/// Creates a new empty tag enumerator.
///
+ /// A new instance.
public IAbCipTagEnumerator Create() => new EmptyAbCipTagEnumerator();
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTagRuntime.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTagRuntime.cs
index 536ec6fc..2876966b 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTagRuntime.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTagRuntime.cs
@@ -11,20 +11,24 @@ public interface IAbCipTagRuntime : IDisposable
{
/// Create the underlying native tag (equivalent to libplctag's plc_tag_create).
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
Task InitializeAsync(CancellationToken cancellationToken);
/// Issue a read; on completion the local buffer holds the current PLC value.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
Task ReadAsync(CancellationToken cancellationToken);
/// Flush the local buffer to the PLC.
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
Task WriteAsync(CancellationToken cancellationToken);
///
/// Raw libplctag status code — mapped to an OPC UA StatusCode via
/// . Zero on success, negative on error.
///
+ /// The raw libplctag status integer; zero on success, negative on error.
int GetStatus();
///
@@ -34,6 +38,7 @@ public interface IAbCipTagRuntime : IDisposable
///
/// CIP data type to decode.
/// Bit index for BOOL-within-DINT extraction, or null.
+ /// The decoded .NET value, or null if the buffer cannot be decoded for the given type.
object? DecodeValue(AbCipDataType type, int? bitIndex);
///
@@ -48,6 +53,7 @@ public interface IAbCipTagRuntime : IDisposable
/// CIP data type to decode.
/// Byte offset in the buffer.
/// Bit index for BOOL-within-DINT extraction, or null.
+ /// The decoded .NET value at the specified offset, or null if the offset is unsupported.
object? DecodeValueAt(AbCipDataType type, int offset, int? bitIndex);
///
@@ -68,6 +74,7 @@ public interface IAbCipTagFactory
{
/// Creates a tag runtime handle from the specified creation parameters.
/// Parameters needed to create the tag runtime.
+ /// A new instance for the specified tag.
IAbCipTagRuntime Create(AbCipTagCreateParams createParams);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTemplateReader.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTemplateReader.cs
index 993db768..8309d8b1 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTemplateReader.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/IAbCipTemplateReader.cs
@@ -16,6 +16,7 @@ public interface IAbCipTemplateReader : IDisposable
/// The device connection parameters.
/// The template instance ID to read.
/// Token to cancel the operation.
+ /// The raw template blob bytes.
Task ReadAsync(
AbCipTagCreateParams deviceParams,
uint templateInstanceId,
@@ -26,5 +27,6 @@ public interface IAbCipTemplateReader : IDisposable
public interface IAbCipTemplateReaderFactory
{
/// Creates a new template reader instance.
+ /// A new instance.
IAbCipTemplateReader Create();
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTagEnumerator.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTagEnumerator.cs
index 26b241a4..99269714 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTagEnumerator.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTagEnumerator.cs
@@ -21,10 +21,7 @@ internal sealed class LibplctagTagEnumerator : IAbCipTagEnumerator
{
private Tag? _tag;
- /// Enumerates all tags in the controller symbol table.
- /// Device connection parameters including gateway and path.
- /// Cancellation token for the enumeration.
- /// An async enumerable of discovered tags.
+ ///
public async IAsyncEnumerable EnumerateAsync(
AbCipTagCreateParams deviceParams,
[EnumeratorCancellation] CancellationToken cancellationToken)
@@ -64,7 +61,6 @@ internal sealed class LibplctagTagEnumerator : IAbCipTagEnumerator
/// Factory for .
internal sealed class LibplctagTagEnumeratorFactory : IAbCipTagEnumeratorFactory
{
- /// Creates a new libplctag-based tag enumerator.
- /// A new tag enumerator instance.
+ ///
public IAbCipTagEnumerator Create() => new LibplctagTagEnumerator();
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTagRuntime.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTagRuntime.cs
index 3f3f46ca..f34dd8ee 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTagRuntime.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTagRuntime.cs
@@ -36,36 +36,22 @@ internal sealed class LibplctagTagRuntime : IAbCipTagRuntime
// negotiates with — Driver.AbCip-013.
}
- /// Initializes the tag asynchronously.
- /// The cancellation token.
- /// A task representing the asynchronous initialization.
+ ///
public Task InitializeAsync(CancellationToken cancellationToken) => _tag.InitializeAsync(cancellationToken);
- /// Reads the tag value asynchronously.
- /// The cancellation token.
- /// A task representing the asynchronous read operation.
+ ///
public Task ReadAsync(CancellationToken cancellationToken) => _tag.ReadAsync(cancellationToken);
- /// Writes the tag value asynchronously.
- /// The cancellation token.
- /// A task representing the asynchronous write operation.
+ ///
public Task WriteAsync(CancellationToken cancellationToken) => _tag.WriteAsync(cancellationToken);
- /// Gets the current status of the tag.
- /// The tag status as an integer.
+ ///
public int GetStatus() => (int)_tag.GetStatus();
- /// Decodes the tag value with the specified data type.
- /// The data type to decode.
- /// The bit index for bit-level access, if applicable.
- /// The decoded value.
+ ///
public object? DecodeValue(AbCipDataType type, int? bitIndex) => DecodeValueAt(type, 0, bitIndex);
- /// Decodes the tag value at the specified offset with the specified data type.
- /// The data type to decode.
- /// The byte offset within the tag buffer.
- /// The bit index for bit-level access, if applicable.
- /// The decoded value.
+ ///
public object? DecodeValueAt(AbCipDataType type, int offset, int? bitIndex) => type switch
{
AbCipDataType.Bool => bitIndex is int bit
@@ -87,10 +73,7 @@ internal sealed class LibplctagTagRuntime : IAbCipTagRuntime
_ => null,
};
- /// Encodes the specified value to the tag with the specified data type.
- /// The data type to encode.
- /// The bit index for bit-level access, if applicable.
- /// The value to encode.
+ ///
public void EncodeValue(AbCipDataType type, int? bitIndex, object? value)
{
switch (type)
@@ -177,9 +160,7 @@ internal sealed class LibplctagTagRuntime : IAbCipTagRuntime
/// Default implementation of IAbCipTagFactory that creates LibplctagTagRuntime instances.
internal sealed class LibplctagTagFactory : IAbCipTagFactory
{
- /// Creates a new tag runtime with the specified creation parameters.
- /// The parameters for creating the tag.
- /// A new IAbCipTagRuntime instance.
+ ///
public IAbCipTagRuntime Create(AbCipTagCreateParams createParams) =>
new LibplctagTagRuntime(createParams);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTemplateReader.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTemplateReader.cs
index bd687f2e..314c6de6 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTemplateReader.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/LibplctagTemplateReader.cs
@@ -25,11 +25,7 @@ internal sealed class LibplctagTemplateReader : IAbCipTemplateReader
{
private Tag? _tag;
- /// Reads a template object from the PLC asynchronously.
- /// The device connection parameters.
- /// The template instance ID to read.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous read operation.
+ ///
public async Task ReadAsync(
AbCipTagCreateParams deviceParams,
uint templateInstanceId,
@@ -50,7 +46,7 @@ internal sealed class LibplctagTemplateReader : IAbCipTemplateReader
return _tag.GetBuffer();
}
- ///
+ /// Disposes the underlying libplctag Tag instance.
public void Dispose() => _tag?.Dispose();
private static PlcType MapPlcType(string attribute) => attribute switch
@@ -64,7 +60,6 @@ internal sealed class LibplctagTemplateReader : IAbCipTemplateReader
internal sealed class LibplctagTemplateReaderFactory : IAbCipTemplateReaderFactory
{
- /// Creates a new instance of the libplctag template reader.
- /// A new instance of .
+ ///
public IAbCipTemplateReader Create() => new LibplctagTemplateReader();
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/PlcFamilies/AbCipPlcFamilyProfile.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/PlcFamilies/AbCipPlcFamilyProfile.cs
index 0c5c3495..9d5460cf 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/PlcFamilies/AbCipPlcFamilyProfile.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/PlcFamilies/AbCipPlcFamilyProfile.cs
@@ -21,6 +21,7 @@ public sealed record AbCipPlcFamilyProfile(
{
/// Look up the profile for a configured family.
/// The PLC family to look up the profile for.
+ /// The profile for the specified PLC family.
public static AbCipPlcFamilyProfile ForFamily(AbCipPlcFamily family) => family switch
{
AbCipPlcFamily.ControlLogix => ControlLogix,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Contracts/AbLegacyPlcFamilyProfile.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Contracts/AbLegacyPlcFamilyProfile.cs
index 8fef30e6..81d3d21b 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Contracts/AbLegacyPlcFamilyProfile.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Contracts/AbLegacyPlcFamilyProfile.cs
@@ -13,6 +13,7 @@ public sealed record AbLegacyPlcFamilyProfile(
{
/// Gets the profile for the specified PLC family.
/// The PLC family.
+ /// The for the specified family.
public static AbLegacyPlcFamilyProfile ForFamily(AbLegacyPlcFamily family) => family switch
{
AbLegacyPlcFamily.Slc500 => Slc500,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/AbLegacyAddress.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/AbLegacyAddress.cs
index a509d951..2422885b 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/AbLegacyAddress.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/AbLegacyAddress.cs
@@ -33,6 +33,7 @@ public sealed record AbLegacyAddress(
string? SubElement)
{
/// Converts the address to the libplctag library address format.
+ /// The libplctag name= attribute string for this address.
public string ToLibplctagName()
{
var file = FileNumber is null ? FileLetter : $"{FileLetter}{FileNumber}";
@@ -44,6 +45,7 @@ public sealed record AbLegacyAddress(
/// Attempts to parse a string into an AB legacy address.
/// The address string to parse.
+ /// A parsed , or if the input is invalid.
public static AbLegacyAddress? TryParse(string? value)
{
if (string.IsNullOrWhiteSpace(value)) return null;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/IAbLegacyTagRuntime.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/IAbLegacyTagRuntime.cs
index 7f1921fa..aca0d9b5 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/IAbLegacyTagRuntime.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/IAbLegacyTagRuntime.cs
@@ -9,22 +9,27 @@ public interface IAbLegacyTagRuntime : IDisposable
{
/// Initializes the tag runtime.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
Task InitializeAsync(CancellationToken cancellationToken);
/// Reads the current value of the tag.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
Task ReadAsync(CancellationToken cancellationToken);
/// Writes the encoded value to the tag.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
Task WriteAsync(CancellationToken cancellationToken);
/// Gets the current status of the tag operation.
+ /// The status code of the last tag operation.
int GetStatus();
/// Decodes the tag value according to the specified data type.
/// The data type to decode.
/// Optional bit index for bit-level access.
+ /// The decoded value, or null if the value cannot be decoded.
object? DecodeValue(AbLegacyDataType type, int? bitIndex);
/// Encodes a value for writing to the tag.
@@ -38,6 +43,7 @@ public interface IAbLegacyTagFactory
{
/// Creates a tag runtime instance with the specified parameters.
/// The tag creation parameters.
+ /// A new tag runtime instance.
IAbLegacyTagRuntime Create(AbLegacyTagCreateParams createParams);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/LibplctagLegacyTagRuntime.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/LibplctagLegacyTagRuntime.cs
index 7caf3c50..d5b3cf3e 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/LibplctagLegacyTagRuntime.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy/LibplctagLegacyTagRuntime.cs
@@ -96,7 +96,7 @@ internal sealed class LibplctagLegacyTagRuntime : IAbLegacyTagRuntime
}
}
- ///
+ /// Disposes the underlying libplctag tag and releases associated resources.
public void Dispose() => _tag.Dispose();
private static PlcType MapPlcType(string attribute) => attribute switch
@@ -111,9 +111,7 @@ internal sealed class LibplctagLegacyTagRuntime : IAbLegacyTagRuntime
internal sealed class LibplctagLegacyTagFactory : IAbLegacyTagFactory
{
- /// Creates a new libplctag-backed tag runtime instance.
- /// The parameters for tag creation.
- /// A new tag runtime instance.
+ ///
public IAbLegacyTagRuntime Create(AbLegacyTagCreateParams createParams) =>
new LibplctagLegacyTagRuntime(createParams);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/FocasDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/FocasDriver.cs
index fefc713a..56792f1d 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/FocasDriver.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/FocasDriver.cs
@@ -65,15 +65,12 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
OnDataChange?.Invoke(this, new DataChangeEventArgs(handle, tagRef, snapshot)));
}
- /// Gets the driver instance identifier.
+ ///
public string DriverInstanceId => _driverInstanceId;
- /// Gets the driver type name.
+ ///
public string DriverType => "FOCAS";
- /// Initializes the driver with configuration and prepares device connections and polling.
- /// JSON configuration string for the driver.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous initialization operation.
+ ///
public Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
Volatile.Write(ref _health, new DriverHealth(DriverState.Initializing, null, null));
@@ -156,19 +153,14 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
return Task.CompletedTask;
}
- /// Reinitializes the driver by shutting down and restarting with new configuration.
- /// JSON configuration string for the driver.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous reinitialization operation.
+ ///
public async Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
await ShutdownAsync(cancellationToken).ConfigureAwait(false);
await InitializeAsync(driverConfigJson, cancellationToken).ConfigureAwait(false);
}
- /// Shuts down the driver, cancelling all running operations and releasing resources.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous shutdown operation.
+ ///
public async Task ShutdownAsync(CancellationToken cancellationToken)
{
await _poll.DisposeAsync().ConfigureAwait(false);
@@ -202,13 +194,11 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
Volatile.Write(ref _health, new DriverHealth(DriverState.Unknown, Volatile.Read(ref _health).LastSuccessfulRead, null));
}
- /// Gets the current health status of the driver.
+ ///
public DriverHealth GetHealth() => Volatile.Read(ref _health);
- /// Gets the current memory footprint of the driver.
+ ///
public long GetMemoryFootprint() => 0;
- /// Flushes optional internal caches.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous cache flush operation.
+ ///
public Task FlushOptionalCachesAsync(CancellationToken cancellationToken) => Task.CompletedTask;
/// Gets the number of configured devices.
@@ -224,10 +214,7 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// ---- IReadable ----
- /// Reads values from one or more tags asynchronously.
- /// A read-only list of tag references to read.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous read operation.
+ ///
public async Task> ReadAsync(
IReadOnlyList fullReferences, CancellationToken cancellationToken)
{
@@ -294,10 +281,7 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// ---- IWritable ----
- /// Writes values to one or more tags asynchronously.
- /// A read-only list of write requests.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous write operation.
+ ///
public async Task> WriteAsync(
IReadOnlyList writes, CancellationToken cancellationToken)
{
@@ -363,10 +347,7 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// ---- ITagDiscovery ----
- /// Discovers tags and builds the OPC UA address space asynchronously.
- /// The address space builder for constructing the OPC UA namespace.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous discovery operation.
+ ///
public Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(builder);
@@ -543,19 +524,12 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// ---- ISubscribable (polling overlay via shared engine) ----
- /// Subscribes to data changes on one or more tags.
- /// A read-only list of tag references to subscribe to.
- /// The interval at which to publish data changes.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous subscription operation.
+ ///
public Task SubscribeAsync(
IReadOnlyList fullReferences, TimeSpan publishingInterval, CancellationToken cancellationToken) =>
Task.FromResult(_poll.Subscribe(fullReferences, publishingInterval));
- /// Unsubscribes from a previous subscription.
- /// The subscription handle to unsubscribe from.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous unsubscription operation.
+ ///
public Task UnsubscribeAsync(ISubscriptionHandle handle, CancellationToken cancellationToken)
{
_poll.Unsubscribe(handle);
@@ -564,7 +538,7 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// ---- IHostConnectivityProbe ----
- /// Gets the connectivity status of all configured devices.
+ ///
public IReadOnlyList GetHostStatuses() =>
[.. _devices.Values.Select(s => new HostConnectivityStatus(s.Options.HostAddress, s.HostState, s.HostStateChangedUtc))];
@@ -970,10 +944,7 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// ---- IAlarmSource ----
- /// Subscribes to alarm events from the driver.
- /// A read-only list of source node IDs to subscribe to.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous subscription operation.
+ ///
public Task SubscribeAlarmsAsync(
IReadOnlyList sourceNodeIds, CancellationToken cancellationToken)
{
@@ -983,17 +954,11 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
return _alarmProjection.SubscribeAsync(sourceNodeIds, cancellationToken);
}
- /// Unsubscribes from a previous alarm subscription.
- /// The alarm subscription handle to unsubscribe from.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous unsubscription operation.
+ ///
public Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken) =>
_alarmProjection is { } p ? p.UnsubscribeAsync(handle, cancellationToken) : Task.CompletedTask;
- /// Acknowledges one or more alarms.
- /// A read-only list of alarm acknowledgement requests.
- /// Cancellation token for the operation.
- /// A task representing the asynchronous acknowledgement operation.
+ ///
public Task AcknowledgeAsync(
IReadOnlyList acknowledgements, CancellationToken cancellationToken) =>
_alarmProjection is { } p ? p.AcknowledgeAsync(acknowledgements, cancellationToken) : Task.CompletedTask;
@@ -1035,9 +1000,7 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
// ---- IPerCallHostResolver ----
- /// Resolves the host address for a given tag reference.
- /// The full reference of the tag.
- /// The host address for the tag reference.
+ ///
public string ResolveHost(string fullReference)
{
if (_tagsByName.TryGetValue(fullReference, out var def))
@@ -1077,6 +1040,7 @@ public sealed class FocasDriver : IDriver, IReadable, IWritable, ITagDiscovery,
/// Disposes the driver and releases all resources synchronously.
public void Dispose() => DisposeAsync().AsTask().GetAwaiter().GetResult();
/// Disposes the driver and releases all resources asynchronously.
+ /// A task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync() => await ShutdownAsync(CancellationToken.None).ConfigureAwait(false);
///
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/IFocasClient.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/IFocasClient.cs
index dbc46cef..21c79e38 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/IFocasClient.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/IFocasClient.cs
@@ -20,6 +20,7 @@ public interface IFocasClient : IDisposable
/// The CNC host address and port.
/// The connection timeout duration.
/// The cancellation token.
+ /// A task that represents the asynchronous connect operation.
Task ConnectAsync(FocasHostAddress address, TimeSpan timeout, CancellationToken cancellationToken);
/// True when the FWLIB handle is valid + the socket is up.
@@ -33,6 +34,7 @@ public interface IFocasClient : IDisposable
/// The CNC memory address to read from.
/// The FOCAS data type to read.
/// The cancellation token.
+ /// A task that resolves to the read value and its OPC UA status code.
Task<(object? value, uint status)> ReadAsync(
FocasAddress address,
FocasDataType type,
@@ -46,6 +48,7 @@ public interface IFocasClient : IDisposable
/// The FOCAS data type to write.
/// The value to write.
/// The cancellation token.
+ /// A task that resolves to the mapped OPC UA status code (0 = Good).
Task WriteAsync(
FocasAddress address,
FocasDataType type,
@@ -57,6 +60,7 @@ public interface IFocasClient : IDisposable
/// responds with any valid status.
///
/// The cancellation token.
+ /// A task that resolves to true when the CNC responds; otherwise false.
Task ProbeAsync(CancellationToken cancellationToken);
///
@@ -66,6 +70,7 @@ public interface IFocasClient : IDisposable
/// emits transitions (raise / clear) on the driver's OnAlarmEvent.
///
/// The cancellation token.
+ /// A task that resolves to the list of currently active alarms.
Task> ReadAlarmsAsync(CancellationToken cancellationToken);
// ---- Fixed-tree T1 (identity + axis discovery + fast-poll dynamic bundle) ----
@@ -76,6 +81,7 @@ public interface IFocasClient : IDisposable
/// values don't change across the session.
///
/// The cancellation token.
+ /// A task that resolves to the CNC system information snapshot.
Task GetSysInfoAsync(CancellationToken cancellationToken);
///
@@ -84,6 +90,7 @@ public interface IFocasClient : IDisposable
/// calls.
///
/// The cancellation token.
+ /// A task that resolves to the list of configured axis names.
Task> GetAxisNamesAsync(CancellationToken cancellationToken);
///
@@ -91,6 +98,7 @@ public interface IFocasClient : IDisposable
/// the Spindle/{name}/ subtree.
///
/// The cancellation token.
+ /// A task that resolves to the list of configured spindle names.
Task> GetSpindleNamesAsync(CancellationToken cancellationToken);
///
@@ -101,6 +109,7 @@ public interface IFocasClient : IDisposable
///
/// The axis index to read dynamics for.
/// The cancellation token.
+ /// A task that resolves to the dynamic snapshot for the specified axis.
Task ReadDynamicAsync(int axisIndex, CancellationToken cancellationToken);
// ---- Fixed-tree T2 (program + operation mode) ----
@@ -113,6 +122,7 @@ public interface IFocasClient : IDisposable
/// on human-operator timescales.
///
/// The cancellation token.
+ /// A task that resolves to the program and operation-mode snapshot.
Task GetProgramInfoAsync(CancellationToken cancellationToken);
// ---- Fixed-tree T3 (timers) ----
@@ -124,6 +134,7 @@ public interface IFocasClient : IDisposable
///
/// The timer kind to read.
/// The cancellation token.
+ /// A task that resolves to the requested cumulative timer reading.
Task GetTimerAsync(FocasTimerKind kind, CancellationToken cancellationToken);
// ---- Fixed-tree T3.5 (servo meters) ----
@@ -134,6 +145,7 @@ public interface IFocasClient : IDisposable
/// disconnected session or unsupported CNC.
///
/// The cancellation token.
+ /// A task that resolves to the list of servo-load meter readings.
Task> GetServoLoadsAsync(CancellationToken cancellationToken);
// ---- Fixed-tree T3.6 (spindle meters) ----
@@ -145,6 +157,7 @@ public interface IFocasClient : IDisposable
/// series like 16i may return EW_FUNC).
///
/// The cancellation token.
+ /// A task that resolves to the list of per-spindle load percentages.
Task> GetSpindleLoadsAsync(CancellationToken cancellationToken);
///
@@ -152,6 +165,7 @@ public interface IFocasClient : IDisposable
/// bootstrap. Index alignment as per .
///
/// The cancellation token.
+ /// A task that resolves to the list of per-spindle maximum RPM values.
Task> GetSpindleMaxRpmsAsync(CancellationToken cancellationToken);
}
@@ -292,9 +306,7 @@ public interface IFocasClientFactory
///
public sealed class UnimplementedFocasClientFactory : IFocasClientFactory
{
- /// Creates a new client instance (always throws NotSupportedException).
- /// Never returns; always throws NotSupportedException.
- /// Always thrown to indicate backend is not yet provisioned.
+ ///
public IFocasClient Create() => throw new NotSupportedException(
"FOCAS driver backend is 'unimplemented'. Switch to 'Backend: \"wire\"' in driver config " +
"once the CNC is provisioned — see docs/drivers/FOCAS.md.");
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/Wire/FocasWireClient.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/Wire/FocasWireClient.cs
index 390a9bdc..d97fb083 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/Wire/FocasWireClient.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/Wire/FocasWireClient.cs
@@ -70,6 +70,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// The FOCAS/2 TCP port (typically 8193).
/// Connection timeout in seconds; zero or negative disables the timeout.
/// Cancellation token for the connect operation.
+ /// A task that represents the asynchronous operation.
public Task ConnectAsync(
string host,
int port,
@@ -90,6 +91,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// The FOCAS/2 TCP port (typically 8193).
/// Connection timeout duration; disables the timeout.
/// Cancellation token for the connect operation.
+ /// A task that represents the asynchronous operation.
public Task ConnectAsync(
string host,
int port,
@@ -183,6 +185,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Async dispose — sends the close PDU when connected and tears down both sockets.
/// Idempotent.
///
+ /// A value task that represents the asynchronous operation.
public async ValueTask DisposeAsync()
{
await _lifetimeGate.WaitAsync(CancellationToken.None).ConfigureAwait(false);
@@ -218,6 +221,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the CNC system info result.
public async Task> ReadSysInfoAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -233,6 +237,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the CNC status result.
public async Task> ReadStatusAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -272,6 +277,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the list of axis name records.
public async Task>> ReadAxisNamesAsync(
short maxCount = 32,
CancellationToken cancellationToken = default,
@@ -288,6 +294,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the list of spindle name records.
public async Task>> ReadSpindleNamesAsync(
short maxCount = 8,
CancellationToken cancellationToken = default,
@@ -308,6 +315,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the dynamic axis data result.
public async Task> ReadDynamic2Async(
short axis = 1,
CancellationToken cancellationToken = default,
@@ -353,6 +361,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the list of servo meter readings.
public async Task>> ReadServoMeterAsync(
short maxCount = 32,
CancellationToken cancellationToken = default,
@@ -390,6 +399,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the list of spindle load metrics.
public Task>> ReadSpindleLoadAsync(
short spindleSelector = -1,
CancellationToken cancellationToken = default,
@@ -402,6 +412,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the list of spindle maximum RPM metrics.
public Task>> ReadSpindleMaxRpmAsync(
short spindleSelector = -1,
CancellationToken cancellationToken = default,
@@ -419,6 +430,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the raw parameter bytes result.
public async Task> ReadParameterBytesAsync(
short dataNumber,
short axis = 0,
@@ -438,6 +450,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the typed parameter result.
public async Task> ReadParameterAsync(
short dataNumber,
short type = 0,
@@ -458,6 +471,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the byte parameter result.
public async Task> ReadParameterByteAsync(short dataNumber, short axis = 0, CancellationToken cancellationToken = default, TimeSpan? timeout = null, ushort? pathId = null)
{
var result = await ReadParameterBytesAsync(dataNumber, axis, cancellationToken, timeout, pathId).ConfigureAwait(false);
@@ -472,6 +486,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the 16-bit integer parameter result.
public async Task> ReadParameterInt16Async(short dataNumber, short axis = 0, CancellationToken cancellationToken = default, TimeSpan? timeout = null, ushort? pathId = null)
{
var result = await ReadParameterBytesAsync(dataNumber, axis, cancellationToken, timeout, pathId).ConfigureAwait(false);
@@ -486,6 +501,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the 32-bit integer parameter result.
public async Task> ReadParameterInt32Async(short dataNumber, short axis = 0, CancellationToken cancellationToken = default, TimeSpan? timeout = null, ushort? pathId = null)
{
var result = await ReadParameterBytesAsync(dataNumber, axis, cancellationToken, timeout, pathId).ConfigureAwait(false);
@@ -500,6 +516,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the single-precision float parameter result.
public async Task> ReadParameterFloat32Async(short dataNumber, short axis = 0, CancellationToken cancellationToken = default, TimeSpan? timeout = null, ushort? pathId = null)
{
var result = await ReadParameterBytesAsync(dataNumber, axis, cancellationToken, timeout, pathId).ConfigureAwait(false);
@@ -514,6 +531,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the double-precision float parameter result.
public async Task> ReadParameterFloat64Async(short dataNumber, short axis = 0, CancellationToken cancellationToken = default, TimeSpan? timeout = null, ushort? pathId = null)
{
var result = await ReadParameterBytesAsync(dataNumber, axis, cancellationToken, timeout, pathId).ConfigureAwait(false);
@@ -527,6 +545,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the macro variable result.
public Task> ReadMacroAsync(
short number,
CancellationToken cancellationToken = default,
@@ -550,6 +569,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the PMC range result.
public async Task> ReadPmcRangeAsync(
short area,
short dataType,
@@ -602,6 +622,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the PMC range result.
public Task> ReadPmcRangeAsync(
FocasPmcArea area,
FocasPmcDataType dataType,
@@ -622,6 +643,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the list of active alarms.
public async Task>> ReadAlarmsAsync(
short type = -1,
short count = 32,
@@ -641,6 +663,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the operation mode result.
public Task> ReadOperationModeAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -658,6 +681,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the raw operation mode code.
public Task> ReadOperationModeCodeAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -671,6 +695,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the executing program name result.
public Task> ReadExecutingProgramNameAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -681,6 +706,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the executed block count.
public Task> ReadBlockCountAsync(
CancellationToken cancellationToken = default,
TimeSpan? timeout = null,
@@ -698,6 +724,7 @@ public sealed class FocasWireClient : IAsyncDisposable, IDisposable
/// Cancellation token for the read operation.
/// Optional per-call timeout override.
/// Optional path ID override; defaults to .
+ /// A task containing the timer value result.
public Task> ReadTimerAsync(
short type,
CancellationToken cancellationToken = default,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/Wire/WireFocasClient.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/Wire/WireFocasClient.cs
index fd6f70de..eed94fa2 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/Wire/WireFocasClient.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS/Wire/WireFocasClient.cs
@@ -36,13 +36,10 @@ public sealed class WireFocasClient : IFocasClient
_wire = new FocasWireClient(logger);
}
- /// Gets a value indicating whether the wire client is connected to the FOCAS host.
+ ///
public bool IsConnected => _wire.IsConnected;
- /// Connects to a FOCAS host at the specified address.
- /// The host address containing the machine name and port.
- /// The connection timeout; values less than or equal to zero are clamped to 1 second.
- /// Cancellation token for the operation.
+ ///
public async Task ConnectAsync(FocasHostAddress address, TimeSpan timeout, CancellationToken cancellationToken)
{
if (_wire.IsConnected) return;
@@ -54,11 +51,7 @@ public sealed class WireFocasClient : IFocasClient
await _wire.ConnectAsync(address.Host, address.Port, effective, cancellationToken).ConfigureAwait(false);
}
- /// Reads a value from the specified FOCAS address.
- /// The FOCAS address to read from.
- /// The FOCAS data type of the value.
- /// Cancellation token for the operation.
- /// A tuple containing the read value and FOCAS status code.
+ ///
public async Task<(object? value, uint status)> ReadAsync(
FocasAddress address, FocasDataType type, CancellationToken cancellationToken)
{
@@ -74,19 +67,12 @@ public sealed class WireFocasClient : IFocasClient
};
}
- /// Writes a value to a FOCAS address (always returns BadNotWritable as OtOpcUa is read-only).
- /// The FOCAS address to write to.
- /// The FOCAS data type of the value.
- /// The value to write.
- /// Cancellation token for the operation.
- /// A task that returns the BadNotWritable status code.
+ ///
public Task WriteAsync(
FocasAddress address, FocasDataType type, object? value, CancellationToken cancellationToken)
=> Task.FromResult(FocasStatusMapper.BadNotWritable);
- /// Probes the FOCAS host to verify connectivity.
- /// Cancellation token for the operation.
- /// True if the probe succeeds; otherwise false.
+ ///
public async Task ProbeAsync(CancellationToken cancellationToken)
{
if (!_wire.IsConnected) return false;
@@ -101,9 +87,7 @@ public sealed class WireFocasClient : IFocasClient
}
}
- /// Reads all active alarms from the FOCAS host.
- /// Cancellation token for the operation.
- /// A list of active alarms; empty if read fails or not connected.
+ ///
public async Task> ReadAlarmsAsync(CancellationToken cancellationToken)
{
if (!_wire.IsConnected) return [];
@@ -125,9 +109,7 @@ public sealed class WireFocasClient : IFocasClient
Message: a.Message ?? string.Empty);
}
- /// Gets system information from the FOCAS host.
- /// Cancellation token for the operation.
- /// The FOCAS system information.
+ ///
public async Task GetSysInfoAsync(CancellationToken cancellationToken)
{
RequireConnected();
@@ -147,9 +129,7 @@ public sealed class WireFocasClient : IFocasClient
AxesCount: axesCount);
}
- /// Gets the names of all axes on the FOCAS host.
- /// Cancellation token for the operation.
- /// A list of axis names; empty if read fails or not connected.
+ ///
public async Task> GetAxisNamesAsync(CancellationToken cancellationToken)
{
if (!_wire.IsConnected) return [];
@@ -169,9 +149,7 @@ public sealed class WireFocasClient : IFocasClient
}
}
- /// Gets the names of all spindles on the FOCAS host.
- /// Cancellation token for the operation.
- /// A list of spindle names; empty if read fails or not connected.
+ ///
public async Task> GetSpindleNamesAsync(CancellationToken cancellationToken)
{
if (!_wire.IsConnected) return [];
@@ -190,10 +168,7 @@ public sealed class WireFocasClient : IFocasClient
}
}
- /// Reads the dynamic state of a specified axis.
- /// The index of the axis to read.
- /// Cancellation token for the operation.
- /// The dynamic snapshot of the axis.
+ ///
public async Task ReadDynamicAsync(int axisIndex, CancellationToken cancellationToken)
{
RequireConnected();
@@ -215,9 +190,7 @@ public sealed class WireFocasClient : IFocasClient
DistanceToGo: pos.Distance);
}
- /// Gets information about the currently executing program.
- /// Cancellation token for the operation.
- /// The current program information.
+ ///
public async Task GetProgramInfoAsync(CancellationToken cancellationToken)
{
RequireConnected();
@@ -245,10 +218,7 @@ public sealed class WireFocasClient : IFocasClient
Mode: modeResult.IsOk ? modeResult.Value : 0);
}
- /// Gets a timer value from the FOCAS host.
- /// The kind of timer to read (run time, cutting time, etc.).
- /// Cancellation token for the operation.
- /// The timer value.
+ ///
public async Task GetTimerAsync(FocasTimerKind kind, CancellationToken cancellationToken)
{
RequireConnected();
@@ -258,9 +228,7 @@ public sealed class WireFocasClient : IFocasClient
return new FocasTimer(kind, t.Minutes, t.Milliseconds);
}
- /// Gets servo load information for all axes.
- /// Cancellation token for the operation.
- /// A list of servo load values for each axis; empty if read fails or not connected.
+ ///
public async Task> GetServoLoadsAsync(CancellationToken cancellationToken)
{
if (!_wire.IsConnected) return [];
@@ -272,15 +240,11 @@ public sealed class WireFocasClient : IFocasClient
.ToList();
}
- /// Gets spindle load information for all spindles.
- /// Cancellation token for the operation.
- /// A list of spindle load percentages; empty if read fails or not connected.
+ ///
public Task> GetSpindleLoadsAsync(CancellationToken cancellationToken) =>
ReadSpindleMetricAsync((sel, ct) => _wire.ReadSpindleLoadAsync(sel, ct), cancellationToken);
- /// Gets maximum RPM information for all spindles.
- /// Cancellation token for the operation.
- /// A list of maximum RPM values for each spindle; empty if read fails or not connected.
+ ///
public Task> GetSpindleMaxRpmsAsync(CancellationToken cancellationToken) =>
ReadSpindleMetricAsync((sel, ct) => _wire.ReadSpindleMaxRpmAsync(sel, ct), cancellationToken);
@@ -427,7 +391,6 @@ public sealed class WireFocasClientFactory : IFocasClientFactory
_logger = logger;
}
- /// Creates a new WireFocasClient instance.
- /// A new IFocasClient implementation.
+ ///
public IFocasClient Create() => new WireFocasClient(_logger);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyBrowseSession.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyBrowseSession.cs
index 431c867c..1734ea97 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyBrowseSession.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyBrowseSession.cs
@@ -22,10 +22,10 @@ internal sealed class GalaxyBrowseSession : IBrowseSession
private volatile bool _disposed;
private IReadOnlyList? _roots;
- /// Opaque token identifying this session in the AdminUI registry.
+ ///
public Guid Token { get; } = Guid.NewGuid();
- /// Wall-clock time of the most recent successful Root/Expand/Attributes call.
+ ///
public DateTime LastUsedUtc { get; private set; } = DateTime.UtcNow;
///
@@ -45,6 +45,8 @@ internal sealed class GalaxyBrowseSession : IBrowseSession
/// returns them as s. Result is cached; a second call
/// returns the cached roots without a re-fetch.
///
+ /// Cancellation token for the operation.
+ /// The top-level browse nodes.
public async Task> RootAsync(CancellationToken cancellationToken)
{
ObjectDisposedException.ThrowIf(_disposed, this);
@@ -69,6 +71,9 @@ internal sealed class GalaxyBrowseSession : IBrowseSession
/// . Throws
/// if the tag hasn't been handed out by a prior Root/Expand call.
///
+ /// The tag name of the node to expand.
+ /// Cancellation token for the operation.
+ /// The direct child browse nodes.
public async Task> ExpandAsync(string nodeId, CancellationToken cancellationToken)
{
ObjectDisposedException.ThrowIf(_disposed, this);
@@ -89,6 +94,9 @@ internal sealed class GalaxyBrowseSession : IBrowseSession
/// via DiscoverHierarchyAsync(MaxDepth=0, RootTagName=nodeId, IncludeAttributes=true).
/// Returns an empty list if the gateway has no matching object.
///
+ /// The tag name of the node to fetch attributes for.
+ /// Cancellation token for the operation.
+ /// The attribute information for the node, or an empty list if not found.
public async Task> AttributesAsync(string nodeId, CancellationToken cancellationToken)
{
ObjectDisposedException.ThrowIf(_disposed, this);
@@ -162,6 +170,7 @@ internal sealed class GalaxyBrowseSession : IBrowseSession
/// Idempotently tears down the underlying repository client. Swallows exceptions
/// on shutdown — the registry's reaper may be racing a client-initiated close.
///
+ /// A task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
if (_disposed) return;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyDriverBrowser.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyDriverBrowser.cs
index 35fcdccd..52a0d7bc 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyDriverBrowser.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser/GalaxyDriverBrowser.cs
@@ -42,7 +42,7 @@ public sealed class GalaxyDriverBrowser : IDriverBrowser
_logger = logger ?? NullLogger.Instance;
}
- /// Driver type key — matches the AdminUI's persisted "GalaxyMxGateway" value.
+ ///
// Hardcoded literal: this project references Driver.Galaxy.Contracts, not Driver.Galaxy,
// so GalaxyDriverFactoryExtensions.DriverTypeName isn't available here.
public string DriverType => "GalaxyMxGateway";
@@ -60,6 +60,7 @@ public sealed class GalaxyDriverBrowser : IDriverBrowser
/// Thrown when the JSON deserialises to null, when Gateway.Endpoint is empty,
/// or when MxAccess.ClientName is empty.
///
+ /// An open browse session over the Galaxy repository client.
public async Task OpenAsync(string configJson, CancellationToken cancellationToken)
{
var opts = JsonSerializer.Deserialize(configJson, JsonOpts)
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/AlarmRefBuilder.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/AlarmRefBuilder.cs
index 2ab50439..e5152c70 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/AlarmRefBuilder.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/AlarmRefBuilder.cs
@@ -39,6 +39,7 @@ internal static class AlarmRefBuilder
/// The full reference of the alarm-bearing attribute.
/// The initial alarm severity level.
/// The initial alarm description.
+ /// An with all five sub-attribute references populated.
public static AlarmConditionInfo Build(
string fullReference,
AlarmSeverity initialSeverity = AlarmSeverity.Medium,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/DataTypeMap.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/DataTypeMap.cs
index 92f08c6c..b9c5f79e 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/DataTypeMap.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/DataTypeMap.cs
@@ -20,6 +20,7 @@ internal static class DataTypeMap
{
/// Maps an MXAccess data type ID to a driver data type.
/// The MXAccess data type ID.
+ /// The corresponding , defaulting to for unknown codes.
public static DriverDataType Map(int mxDataType) => mxDataType switch
{
0 => DriverDataType.Boolean,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/DeployWatcher.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/DeployWatcher.cs
index c11325fb..aa1649d5 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/DeployWatcher.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/DeployWatcher.cs
@@ -98,6 +98,7 @@ public sealed class DeployWatcher : IDisposable
}
/// Cancels the loop and waits for it to exit cleanly.
+ /// A task that represents the asynchronous stop operation.
public async Task StopAsync()
{
var cts = _cts;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GalaxyDiscoverer.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GalaxyDiscoverer.cs
index d07c79e3..65f579d8 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GalaxyDiscoverer.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GalaxyDiscoverer.cs
@@ -39,6 +39,7 @@ public sealed class GalaxyDiscoverer
///
/// The address space builder to populate with discovery results.
/// The cancellation token for the operation.
+ /// A task that represents the asynchronous discovery operation.
public async Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(builder);
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GatewayGalaxyDeployWatchSource.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GatewayGalaxyDeployWatchSource.cs
index c984c251..4486efc8 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GatewayGalaxyDeployWatchSource.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GatewayGalaxyDeployWatchSource.cs
@@ -22,10 +22,7 @@ public sealed class GatewayGalaxyDeployWatchSource : IGalaxyDeployWatchSource
_client = client ?? throw new ArgumentNullException(nameof(client));
}
- /// Watches for deploy events asynchronously.
- /// The last deploy time that was observed.
- /// The cancellation token.
- /// An async enumerable of deploy events.
+ ///
public IAsyncEnumerable WatchAsync(
DateTimeOffset? lastSeenDeployTime, CancellationToken cancellationToken)
=> _client.WatchDeployEventsAsync(lastSeenDeployTime, cancellationToken);
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GatewayGalaxyHierarchySource.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GatewayGalaxyHierarchySource.cs
index d3382ddb..9cd4cc3f 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GatewayGalaxyHierarchySource.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/GatewayGalaxyHierarchySource.cs
@@ -24,6 +24,7 @@ public sealed class GatewayGalaxyHierarchySource : IGalaxyHierarchySource
/// Discovers the Galaxy object hierarchy asynchronously via the gateway.
///
/// Cancellation token for the operation.
+ /// A task that resolves to the full list of Galaxy objects in the hierarchy.
public Task> GetHierarchyAsync(CancellationToken cancellationToken)
=> _client.DiscoverHierarchyAsync(cancellationToken);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/IGalaxyDeployWatchSource.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/IGalaxyDeployWatchSource.cs
index 8ed170d3..7e981c73 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/IGalaxyDeployWatchSource.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/IGalaxyDeployWatchSource.cs
@@ -21,6 +21,7 @@ public interface IGalaxyDeployWatchSource
///
/// The last seen deploy time, or null to receive a bootstrap event.
/// The cancellation token.
+ /// An async stream of deploy events.
IAsyncEnumerable WatchAsync(
DateTimeOffset? lastSeenDeployTime, CancellationToken cancellationToken);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/IGalaxyHierarchySource.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/IGalaxyHierarchySource.cs
index fd3c0b06..7512b185 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/IGalaxyHierarchySource.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Browse/IGalaxyHierarchySource.cs
@@ -16,5 +16,6 @@ public interface IGalaxyHierarchySource
/// callers don't reimplement paging.
///
/// Cancellation token for the operation.
+ /// A task that resolves to the full materialised Galaxy object hierarchy.
Task> GetHierarchyAsync(CancellationToken cancellationToken);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs
index 1bcc63b6..c52e9950 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriver.cs
@@ -126,7 +126,7 @@ public sealed class GalaxyDriver
/// Fires when a host transitions Running ↔ Stopped (PR 4.7 HostStatusAggregator).
public event EventHandler? OnHostStatusChanged;
- ///
+ /// Fires when an alarm event is received from the Galaxy alarm feed.
public event EventHandler? OnAlarmEvent;
/// Initializes a new instance of the class.
@@ -202,6 +202,7 @@ public sealed class GalaxyDriver
/// asserted deterministically (Driver.Galaxy-013).
///
/// Cancellation token for the replay operation.
+ /// A task that represents the asynchronous replay operation.
internal Task InvokeReplayForTestAsync(CancellationToken cancellationToken) =>
ReplayAsync(cancellationToken);
@@ -449,6 +450,7 @@ public sealed class GalaxyDriver
/// changing the call site.
///
/// The secret reference string to resolve.
+ /// The resolved API key string.
internal static string ResolveApiKey(string secretRef) => ResolveApiKey(secretRef, logger: null);
///
@@ -459,6 +461,7 @@ public sealed class GalaxyDriver
///
/// The secret reference string to resolve.
/// Optional logger for warning on cleartext keys.
+ /// The resolved API key string.
internal static string ResolveApiKey(string secretRef, ILogger? logger)
{
ArgumentException.ThrowIfNullOrEmpty(secretRef);
@@ -1205,6 +1208,7 @@ public sealed class GalaxyDriver
/// GetAwaiter().GetResult() for every async sub-component, risking a
/// deadlock under thread-pool starvation).
///
+ /// A value task that represents the asynchronous disposal operation.
public async ValueTask DisposeAsync()
{
if (_disposed) return;
@@ -1278,26 +1282,18 @@ public sealed class GalaxyDriver
System.Collections.Concurrent.ConcurrentDictionary map)
: IAddressSpaceBuilder
{
- /// Creates a folder node and returns a builder for populating it.
- /// The OPC UA BrowseName of the folder.
- /// The display name for the folder.
+ ///
public IAddressSpaceBuilder Folder(string browseName, string displayName)
=> new SecurityCapturingBuilder(inner.Folder(browseName, displayName), map);
- /// Creates a variable node and captures its security classification.
- /// The OPC UA BrowseName of the variable.
- /// The display name for the variable.
- /// The driver attribute metadata including security classification.
+ ///
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo attributeInfo)
{
map[attributeInfo.FullName] = attributeInfo.SecurityClass;
return inner.Variable(browseName, displayName, attributeInfo);
}
- /// Adds a property node to the current parent.
- /// The OPC UA BrowseName of the property.
- /// The OPC UA data type of the property.
- /// The property value.
+ ///
public void AddProperty(string browseName, DriverDataType dataType, object? value)
=> inner.AddProperty(browseName, dataType, value);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriverFactoryExtensions.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriverFactoryExtensions.cs
index 328aae88..3b92c059 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriverFactoryExtensions.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/GalaxyDriverFactoryExtensions.cs
@@ -35,6 +35,7 @@ public static class GalaxyDriverFactoryExtensions
/// Convenience for tests + standalone callers.
/// The unique identifier for the driver instance.
/// The driver configuration in JSON format.
+ /// A configured instance.
public static GalaxyDriver CreateInstance(string driverInstanceId, string driverConfigJson)
=> CreateInstance(driverInstanceId, driverConfigJson, loggerFactory: null);
@@ -42,6 +43,7 @@ public static class GalaxyDriverFactoryExtensions
/// The unique identifier for the driver instance.
/// The driver configuration in JSON format.
/// The optional logger factory for creating drivers.
+ /// A configured instance.
public static GalaxyDriver CreateInstance(
string driverInstanceId, string driverConfigJson, ILoggerFactory? loggerFactory)
{
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Health/HostStatusAggregator.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Health/HostStatusAggregator.cs
index a606f908..cea862d3 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Health/HostStatusAggregator.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Health/HostStatusAggregator.cs
@@ -38,6 +38,7 @@ public sealed class HostStatusAggregator
/// Snapshot the current host set. Suitable as the body of
/// IHostConnectivityProbe.GetHostStatuses().
///
+ /// A snapshot of all currently tracked host connectivity statuses.
public IReadOnlyList Snapshot()
{
lock (_lock)
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Health/PerPlatformProbeWatcher.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Health/PerPlatformProbeWatcher.cs
index daefb2ea..b766e38b 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Health/PerPlatformProbeWatcher.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Health/PerPlatformProbeWatcher.cs
@@ -77,6 +77,7 @@ public sealed class PerPlatformProbeWatcher : IDisposable
///
/// The platform tag names to synchronize.
/// A cancellation token to cancel the operation.
+ /// A task that represents the asynchronous operation.
public async Task SyncPlatformsAsync(
IEnumerable platformTagNames, CancellationToken cancellationToken)
{
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GalaxyMxSession.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GalaxyMxSession.cs
index 7913c69c..746ef7ca 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GalaxyMxSession.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GalaxyMxSession.cs
@@ -55,6 +55,7 @@ public sealed class GalaxyMxSession : IAsyncDisposable
///
/// The MX gateway client options.
/// The cancellation token.
+ /// A task that represents the asynchronous connect operation.
public async Task ConnectAsync(MxGatewayClientOptions clientOptions, CancellationToken cancellationToken)
{
ObjectDisposedException.ThrowIf(_disposed, this);
@@ -89,6 +90,7 @@ public sealed class GalaxyMxSession : IAsyncDisposable
public MxGatewaySession? Session => _session;
/// Disposes the session and underlying gateway client resources.
+ /// A value task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
if (_disposed) return;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GalaxySubscriptionHandle.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GalaxySubscriptionHandle.cs
index 9103e395..290984d6 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GalaxySubscriptionHandle.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GalaxySubscriptionHandle.cs
@@ -8,6 +8,6 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Runtime;
///
internal sealed record GalaxySubscriptionHandle(long SubscriptionId) : ISubscriptionHandle
{
- /// Gets the diagnostic identifier for the subscription.
+ ///
public string DiagnosticId => $"galaxy-sub-{SubscriptionId}";
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxyAlarmAcknowledger.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxyAlarmAcknowledger.cs
index 19b957da..d5fc35f1 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxyAlarmAcknowledger.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxyAlarmAcknowledger.cs
@@ -37,6 +37,7 @@ internal sealed class GatewayGalaxyAlarmAcknowledger : IGalaxyAlarmAcknowledger
/// An operator-supplied comment attached to the acknowledgement.
/// The name of the operator performing the acknowledgement.
/// A token to cancel the asynchronous operation.
+ /// A task that represents the asynchronous acknowledge operation.
public async Task AcknowledgeAsync(
string alarmFullReference,
string comment,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxyAlarmFeed.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxyAlarmFeed.cs
index e01c1c61..3a584f30 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxyAlarmFeed.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxyAlarmFeed.cs
@@ -39,6 +39,7 @@ internal sealed class GatewayGalaxyAlarmFeed : IGalaxyAlarmFeed
///
/// The stream request parameters.
/// A cancellation token.
+ /// An async enumerable of alarm feed messages from the gateway stream.
internal delegate IAsyncEnumerable AlarmStreamFactory(
StreamAlarmsRequest request, CancellationToken cancellationToken);
@@ -261,6 +262,7 @@ internal sealed class GatewayGalaxyAlarmFeed : IGalaxyAlarmFeed
};
/// Releases the alarm feed resources and stops the background stream task.
+ /// A that completes when the background stream loop has stopped.
public async ValueTask DisposeAsync()
{
if (_disposed) return;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxySubscriber.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxySubscriber.cs
index e38430f6..664b9b2d 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxySubscriber.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/GatewayGalaxySubscriber.cs
@@ -28,11 +28,7 @@ public sealed class GatewayGalaxySubscriber : IGalaxySubscriber
_session = session ?? throw new ArgumentNullException(nameof(session));
}
- /// Subscribes to a bulk list of Galaxy references with optional buffered update interval.
- /// The full Galaxy tag references to subscribe to.
- /// The buffered update interval in milliseconds.
- /// The cancellation token.
- /// A task that returns a list of subscribe results.
+ ///
public async Task> SubscribeBulkAsync(
IReadOnlyList fullReferences, int bufferedUpdateIntervalMs, CancellationToken cancellationToken)
{
@@ -100,10 +96,7 @@ public sealed class GatewayGalaxySubscriber : IGalaxySubscriber
}
}
- /// Unsubscribes from a bulk list of item handles.
- /// The item handles to unsubscribe from.
- /// The cancellation token.
- /// A task representing the unsubscribe operation.
+ ///
public async Task UnsubscribeBulkAsync(IReadOnlyList itemHandles, CancellationToken cancellationToken)
{
if (itemHandles.Count == 0) return;
@@ -117,9 +110,7 @@ public sealed class GatewayGalaxySubscriber : IGalaxySubscriber
.ConfigureAwait(false);
}
- /// Streams Galaxy MX events asynchronously.
- /// The cancellation token.
- /// An async enumerable of MX events.
+ ///
public IAsyncEnumerable StreamEventsAsync(CancellationToken cancellationToken)
{
var session = _session.Session
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxyAlarmAcknowledger.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxyAlarmAcknowledger.cs
index aa9b1c89..752c4c30 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxyAlarmAcknowledger.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxyAlarmAcknowledger.cs
@@ -24,6 +24,7 @@ internal interface IGalaxyAlarmAcknowledger
/// OPC UA session by the server-side ACL layer before reaching the driver.
///
/// Cancels the gateway RPC.
+ /// A task that represents the asynchronous acknowledge operation.
Task AcknowledgeAsync(
string alarmFullReference,
string comment,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxyDataWriter.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxyDataWriter.cs
index f91e66e2..7b78e2d5 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxyDataWriter.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxyDataWriter.cs
@@ -26,6 +26,7 @@ public interface IGalaxyDataWriter
/// (the safest default — non-secured Write).
///
/// Aborts the in-flight batch.
+ /// A task resolving to one per input entry, in input order.
Task> WriteAsync(
IReadOnlyList writes,
Func securityResolver,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxySubscriber.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxySubscriber.cs
index 9d33968e..3c66c9cb 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxySubscriber.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/IGalaxySubscriber.cs
@@ -20,12 +20,14 @@ public interface IGalaxySubscriber
/// The list of tag references to subscribe to.
/// The buffered update interval in milliseconds.
/// Cancellation token for the operation.
+ /// A task that resolves to one per requested reference, in input order.
Task> SubscribeBulkAsync(
IReadOnlyList fullReferences, int bufferedUpdateIntervalMs, CancellationToken cancellationToken);
/// Unsubscribe a batch of item handles obtained from .
/// The item handles to unsubscribe.
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
Task UnsubscribeBulkAsync(IReadOnlyList itemHandles, CancellationToken cancellationToken);
///
@@ -34,5 +36,6 @@ public interface IGalaxySubscriber
/// its .
///
/// Cancellation token for the stream.
+ /// An async sequence of items emitted by the gateway.
IAsyncEnumerable StreamEventsAsync(CancellationToken cancellationToken);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/MxAccessSeverityMapper.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/MxAccessSeverityMapper.cs
index 338b94fa..a2e6897a 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/MxAccessSeverityMapper.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/MxAccessSeverityMapper.cs
@@ -37,6 +37,7 @@ internal static class MxAccessSeverityMapper
/// + OPC UA Part 9 numeric severity tuple.
///
/// The raw MXAccess severity value (0-999 range, clamped if out of range).
+ /// A tuple of the OPC UA bucket and the corresponding Part 9 numeric severity.
public static (AlarmSeverity Bucket, int OpcUaSeverity) Map(int rawMxAccessSeverity)
{
if (rawMxAccessSeverity < 250)
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/MxValueDecoder.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/MxValueDecoder.cs
index 93f60aad..09ed4f0f 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/MxValueDecoder.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/MxValueDecoder.cs
@@ -15,6 +15,7 @@ internal static class MxValueDecoder
{
/// Decodes a gateway MxValue into a boxed CLR object.
/// The MxValue to decode, or null.
+ /// The decoded CLR value, or null when the input is null or empty.
public static object? Decode(MxValue? value)
{
if (value is null) return null;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/ReconnectSupervisor.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/ReconnectSupervisor.cs
index 6e3fbd90..a3ea49d8 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/ReconnectSupervisor.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/ReconnectSupervisor.cs
@@ -147,6 +147,7 @@ public sealed class ReconnectSupervisor : IDisposable
/// and for orchestration that wants to gate calls on recovery completing.
///
/// Token to cancel the wait operation.
+ /// A task that completes when the supervisor reaches the Healthy state or the token is cancelled.
public async Task WaitForHealthyAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested && IsDegraded)
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/SubscriptionRegistry.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/SubscriptionRegistry.cs
index 1f70e82f..b3ca1604 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/SubscriptionRegistry.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/SubscriptionRegistry.cs
@@ -32,6 +32,7 @@ internal sealed class SubscriptionRegistry
public int TrackedItemHandleCount => _subscribersByItemHandle.Count;
/// Allocate a fresh subscription id. Monotonic; unique per registry lifetime.
+ /// A new unique subscription identifier.
public long NextSubscriptionId() => Interlocked.Increment(ref _nextSubscriptionId);
///
@@ -108,6 +109,7 @@ internal sealed class SubscriptionRegistry
}
/// Snapshot every active binding for diagnostic output.
+ /// A flat list of all active tag bindings across all subscriptions.
public IReadOnlyList SnapshotAllBindings() =>
[.. _bySubscriptionId.Values.SelectMany(entry => entry.Bindings)];
@@ -116,6 +118,7 @@ internal sealed class SubscriptionRegistry
/// Used by the reconnect replay path so it can re-issue SubscribeBulk per subscription
/// and then each one with the post-reconnect item handles.
///
+ /// A list of (SubscriptionId, Bindings) pairs for all active subscriptions.
public IReadOnlyList<(long SubscriptionId, IReadOnlyList Bindings)> SnapshotEntries() =>
[.. _bySubscriptionId.Values.Select(entry => (entry.SubscriptionId, entry.Bindings))];
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/TracedGalaxyDataWriter.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/TracedGalaxyDataWriter.cs
index 4c15b21c..2f87fb9c 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/TracedGalaxyDataWriter.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/TracedGalaxyDataWriter.cs
@@ -14,6 +14,7 @@ internal sealed class TracedGalaxyDataWriter(IGalaxyDataWriter inner, string cli
/// The list of write requests to process.
/// Function to resolve security classification for tag references.
/// Cancellation token for the operation.
+ /// A task that resolves to the write results for each request.
public async Task> WriteAsync(
IReadOnlyList writes,
Func securityResolver,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/TracedGalaxySubscriber.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/TracedGalaxySubscriber.cs
index 55717860..a951f9a6 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/TracedGalaxySubscriber.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Galaxy/Runtime/TracedGalaxySubscriber.cs
@@ -10,10 +10,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Runtime;
///
internal sealed class TracedGalaxySubscriber(IGalaxySubscriber inner, string clientName) : IGalaxySubscriber
{
- /// Subscribes to multiple Galaxy tags in bulk with tracing.
- /// The full tag references to subscribe to.
- /// The buffered update interval in milliseconds.
- /// The cancellation token.
+ ///
public async Task> SubscribeBulkAsync(
IReadOnlyList fullReferences, int bufferedUpdateIntervalMs, CancellationToken cancellationToken)
{
@@ -35,9 +32,7 @@ internal sealed class TracedGalaxySubscriber(IGalaxySubscriber inner, string cli
}
}
- /// Unsubscribes from multiple Galaxy tags in bulk with tracing.
- /// The item handles to unsubscribe from.
- /// The cancellation token.
+ ///
public async Task UnsubscribeBulkAsync(IReadOnlyList itemHandles, CancellationToken cancellationToken)
{
using var activity = GalaxyTelemetry.ActivitySource.StartActivity("galaxy.unsubscribe_bulk");
@@ -60,6 +55,7 @@ internal sealed class TracedGalaxySubscriber(IGalaxySubscriber inner, string cli
/// visibility through 's metrics in PR 6.2 instead.
///
/// The cancellation token.
+ /// An async sequence of items forwarded from the inner subscriber.
public async IAsyncEnumerable StreamEventsAsync(
[EnumeratorCancellation] CancellationToken cancellationToken)
{
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client/Ipc/FrameWriter.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client/Ipc/FrameWriter.cs
index 33e9609d..130c760c 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client/Ipc/FrameWriter.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client/Ipc/FrameWriter.cs
@@ -26,6 +26,7 @@ public sealed class FrameWriter : IDisposable
/// The frame message kind tag.
/// The message object to serialize and write.
/// The cancellation token.
+ /// A task that represents the asynchronous write operation.
public async Task WriteAsync(MessageKind kind, T message, CancellationToken ct)
{
var body = MessagePackSerializer.Serialize(message, cancellationToken: ct);
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client/WonderwareHistorianClient.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client/WonderwareHistorianClient.cs
index 2aacfbcf..a29c8ca9 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client/WonderwareHistorianClient.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Client/WonderwareHistorianClient.cs
@@ -66,13 +66,7 @@ public sealed class WonderwareHistorianClient : IHistorianDataSource, IAlarmHist
// ===== IHistorianDataSource =====
- /// Asynchronously reads raw historical data for a tag within a time range.
- /// The full reference path of the tag to read.
- /// The start time in UTC for the read range.
- /// The end time in UTC for the read range.
- /// The maximum number of values to return.
- /// The cancellation token.
- /// A task that returns the historical read result.
+ ///
public async Task ReadRawAsync(
string fullReference, DateTime startUtc, DateTime endUtc, uint maxValuesPerNode,
CancellationToken cancellationToken)
@@ -91,14 +85,7 @@ public sealed class WonderwareHistorianClient : IHistorianDataSource, IAlarmHist
return new HistoryReadResult(ToSnapshots(reply.Samples), ContinuationPoint: null);
}
- /// Asynchronously reads processed historical data with aggregation for a tag within a time range.
- /// The full reference path of the tag to read.
- /// The start time in UTC for the read range.
- /// The end time in UTC for the read range.
- /// The time interval for aggregation.
- /// The type of aggregation to apply.
- /// The cancellation token.
- /// A task that returns the historical read result with aggregated data.
+ ///
public async Task ReadProcessedAsync(
string fullReference, DateTime startUtc, DateTime endUtc, TimeSpan interval,
HistoryAggregateType aggregate, CancellationToken cancellationToken)
@@ -118,11 +105,7 @@ public sealed class WonderwareHistorianClient : IHistorianDataSource, IAlarmHist
return new HistoryReadResult(ToAggregateSnapshots(reply.Buckets), ContinuationPoint: null);
}
- /// Asynchronously reads historical data at specific timestamps for a tag.
- /// The full reference path of the tag to read.
- /// The specific timestamps in UTC to read values for.
- /// The cancellation token.
- /// A task that returns the historical read result with values at the specified times.
+ ///
public async Task ReadAtTimeAsync(
string fullReference, IReadOnlyList timestampsUtc, CancellationToken cancellationToken)
{
@@ -184,13 +167,7 @@ public sealed class WonderwareHistorianClient : IHistorianDataSource, IAlarmHist
return result;
}
- /// Asynchronously reads historical events within a time range.
- /// The source name filter for events, or null to read all sources.
- /// The start time in UTC for the read range.
- /// The end time in UTC for the read range.
- /// The maximum number of events to return.
- /// The cancellation token.
- /// A task that returns the historical events result.
+ ///
public async Task ReadEventsAsync(
string? sourceName, DateTime startUtc, DateTime endUtc, int maxEvents,
CancellationToken cancellationToken)
@@ -231,6 +208,7 @@ public sealed class WonderwareHistorianClient : IHistorianDataSource, IAlarmHist
/// incremented any counter). (Finding 003 / 004.)
///
///
+ /// A reflecting current operation counters and channel connection state.
public HistorianHealthSnapshot GetHealthSnapshot()
{
lock (_healthLock)
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/AahClientManagedAlarmEventWriter.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/AahClientManagedAlarmEventWriter.cs
index 71e46bdb..c25e2ab3 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/AahClientManagedAlarmEventWriter.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/AahClientManagedAlarmEventWriter.cs
@@ -37,6 +37,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
///
/// The alarm events to write.
/// Cancellation token.
+ /// A task resolving to a bool array where each element indicates whether the corresponding event was acknowledged.
public async Task WriteAsync(AlarmHistorianEventDto[] events, CancellationToken cancellationToken)
{
if (events is null || events.Length == 0)
@@ -91,6 +92,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
/// The HRESULT code from the SDK call.
/// Indicates whether the error is a communication-class error.
/// Indicates whether the input was malformed.
+ /// The write outcome for the SDK call result.
public static AlarmHistorianWriteOutcome MapOutcome(int hresult, bool isCommunicationError, bool isMalformedInput)
{
// Order matters: malformed input is permanent regardless of HRESULT pattern;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/HistorianClusterEndpointPicker.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/HistorianClusterEndpointPicker.cs
index a65ff312..37be9db1 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/HistorianClusterEndpointPicker.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/HistorianClusterEndpointPicker.cs
@@ -48,6 +48,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
}
/// Gets the list of currently healthy nodes.
+ /// A read-only list of node names that are currently healthy and not in cooldown.
public IReadOnlyList GetHealthyNodes()
{
lock (_lock)
@@ -101,6 +102,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
}
/// Returns a snapshot of all node states.
+ /// A list of objects representing each configured node.
public List SnapshotNodeStates()
{
lock (_lock)
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/HistorianDataSource.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/HistorianDataSource.cs
index 22f3afb8..02877e3f 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/HistorianDataSource.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/HistorianDataSource.cs
@@ -83,6 +83,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
/// shared SDK connection should therefore be reset. Internal for unit testing.
///
/// The historian access error code.
+ /// true if the error code indicates a connection-class failure; otherwise false.
internal static bool IsConnectionClassError(HistorianAccessError.ErrorValue code)
=> ConnectionErrorCodes.Contains(code);
@@ -97,6 +98,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
///
/// The historian configuration.
/// The cancellation token.
+ /// A linked pre-wired with the optional request timeout.
internal static CancellationTokenSource BuildRequestCts(HistorianConfiguration cfg, CancellationToken ct)
{
var cts = CancellationTokenSource.CreateLinkedTokenSource(ct);
@@ -160,7 +162,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
};
}
- /// Gets a snapshot of the current health status.
+ ///
public HistorianHealthSnapshot GetHealthSnapshot()
{
var nodeStates = _picker.SnapshotNodeStates();
@@ -396,12 +398,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
}
}
- /// Reads raw historical samples for the specified tag.
- /// The tag name.
- /// The start time for the query.
- /// The end time for the query.
- /// The maximum number of values to return.
- /// Cancellation token for the operation.
+ ///
public Task> ReadRawAsync(
string tagName, DateTime startTime, DateTime endTime, int maxValues,
CancellationToken ct = default)
@@ -485,13 +482,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
return Task.FromResult(results);
}
- /// Reads aggregate historical samples for the specified tag.
- /// The tag name.
- /// The start time for the query.
- /// The end time for the query.
- /// The interval in milliseconds.
- /// The aggregate column name.
- /// Cancellation token for the operation.
+ ///
public Task> ReadAggregateAsync(
string tagName, DateTime startTime, DateTime endTime,
double intervalMs, string aggregateColumn,
@@ -572,10 +563,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
return Task.FromResult(results);
}
- /// Reads historical samples at specific timestamps for the specified tag.
- /// The tag name.
- /// The timestamps to read.
- /// Cancellation token for the operation.
+ ///
public Task> ReadAtTimeAsync(
string tagName, DateTime[] timestamps,
CancellationToken ct = default)
@@ -658,12 +646,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
return Task.FromResult(results);
}
- /// Reads historical events within the specified time range.
- /// The optional event source name filter.
- /// The start time for the query.
- /// The end time for the query.
- /// The maximum number of events to return.
- /// Cancellation token for the operation.
+ ///
public Task> ReadEventsAsync(
string? sourceName, DateTime startTime, DateTime endTime, int maxEvents,
CancellationToken ct = default)
@@ -764,6 +747,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
///
///
/// The history query result.
+ /// The resolved value — the string value when non-empty and numeric value is zero, otherwise the numeric value.
internal static object? SelectValue(HistoryQueryResult result)
=> SelectValueFromPair(result.Value, result.StringValue);
@@ -775,6 +759,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
///
/// The numeric value.
/// The string value.
+ /// The string value when non-empty and numeric value is zero, otherwise the numeric value.
internal static object? SelectValueFromPair(double value, string? stringValue)
{
if (!string.IsNullOrEmpty(stringValue) && value == 0)
@@ -785,6 +770,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
/// Extracts the specified aggregate value from an analog summary query result.
/// The analog summary query result.
/// The aggregate column name.
+ /// The value of the specified aggregate column, or null if the column name is unknown.
internal static double? ExtractAggregateValue(AnalogSummaryQueryResult result, string column)
{
switch (column)
@@ -800,7 +786,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
}
}
- /// Disposes the historian data source and releases its resources.
+ ///
public void Dispose()
{
if (_disposed) return;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/IAlarmHistorianWriteBackend.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/IAlarmHistorianWriteBackend.cs
index 3c655a15..b0e9df38 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/IAlarmHistorianWriteBackend.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/IAlarmHistorianWriteBackend.cs
@@ -25,6 +25,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
///
/// The events to write to the historian.
/// Token to cancel the operation.
+ /// A task that resolves to one per input event, in the same order.
Task WriteBatchAsync(
AlarmHistorianEventDto[] events,
CancellationToken cancellationToken);
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/SdkAlarmHistorianWriteBackend.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/SdkAlarmHistorianWriteBackend.cs
index c1a2a9b6..3f2886e3 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/SdkAlarmHistorianWriteBackend.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Backend/SdkAlarmHistorianWriteBackend.cs
@@ -103,10 +103,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
_picker = picker ?? new HistorianClusterEndpointPicker(config);
}
- /// Writes a batch of alarm events to the historian, returning outcomes for each event.
- /// The alarm events to write.
- /// The cancellation token.
- /// An array of outcomes corresponding to each input event.
+ ///
public Task WriteBatchAsync(
AlarmHistorianEventDto[] events,
CancellationToken cancellationToken)
@@ -379,7 +376,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware.Backend
RequestTimeoutSeconds = _config.RequestTimeoutSeconds,
};
- /// Disposes the connection and releases resources.
+ ///
public void Dispose()
{
if (_disposed) return;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/FrameReader.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/FrameReader.cs
index 7593a408..39473c39 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/FrameReader.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/FrameReader.cs
@@ -52,6 +52,7 @@ public sealed class FrameReader : IDisposable
/// Deserializes the message body to the specified type.
/// The type to deserialize to.
/// The serialized message body.
+ /// The deserialized value of type .
public static T Deserialize(byte[] body) => MessagePackSerializer.Deserialize(body);
private async Task ReadExactAsync(byte[] buffer, CancellationToken ct)
@@ -70,7 +71,7 @@ public sealed class FrameReader : IDisposable
return true;
}
- /// Disposes the frame reader and optionally closes the underlying stream.
+ ///
public void Dispose()
{
if (!_leaveOpen) _stream.Dispose();
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/FrameWriter.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/FrameWriter.cs
index fd88a7e7..de6c05e6 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/FrameWriter.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/FrameWriter.cs
@@ -32,6 +32,7 @@ public sealed class FrameWriter : IDisposable
/// The message kind identifier.
/// The message to serialize and write.
/// The cancellation token.
+ /// A task that represents the asynchronous write operation.
public async Task WriteAsync(MessageKind kind, T message, CancellationToken ct)
{
var body = MessagePackSerializer.Serialize(message, cancellationToken: ct);
@@ -57,7 +58,7 @@ public sealed class FrameWriter : IDisposable
finally { _gate.Release(); }
}
- /// Disposes the frame writer and releases resources.
+ ///
public void Dispose()
{
_gate.Dispose();
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/HistorianFrameHandler.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/HistorianFrameHandler.cs
index 9eb9c915..9b70e9df 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/HistorianFrameHandler.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/HistorianFrameHandler.cs
@@ -34,11 +34,7 @@ public sealed class HistorianFrameHandler : IFrameHandler
_alarmWriter = alarmWriter;
}
- /// Handles an incoming frame by dispatching to the appropriate historian operation.
- /// The frame message kind.
- /// The frame body bytes.
- /// The frame writer for sending responses.
- /// Cancellation token.
+ ///
public Task HandleAsync(MessageKind kind, byte[] body, FrameWriter writer, CancellationToken ct)
=> kind switch
{
@@ -262,5 +258,6 @@ public interface IAlarmEventWriter
///
/// Alarm events to write.
/// Cancellation token.
+ /// A task that resolves to an array of booleans indicating whether each event was successfully persisted.
Task WriteAsync(AlarmHistorianEventDto[] events, CancellationToken cancellationToken);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/PipeServer.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/PipeServer.cs
index ffd9cb0c..298189ed 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/PipeServer.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Ipc/PipeServer.cs
@@ -32,6 +32,7 @@ public sealed class PipeServer : IDisposable
/// The named pipe server stream to verify.
/// The allowed security identifier.
/// The rejection reason if verification fails.
+ /// if the caller is verified; with a populated otherwise.
internal delegate bool CallerVerifier(NamedPipeServerStream pipe, SecurityIdentifier allowedSid, out string reason);
/// Initializes a new instance of the class.
@@ -68,6 +69,7 @@ public sealed class PipeServer : IDisposable
///
/// The frame handler to process frames.
/// Cancellation token for the operation.
+ /// A task that completes when the client disconnects or the operation is cancelled.
public async Task RunOneConnectionAsync(IFrameHandler handler, CancellationToken ct)
{
using var linked = CancellationTokenSource.CreateLinkedTokenSource(_cts.Token, ct);
@@ -179,6 +181,7 @@ public sealed class PipeServer : IDisposable
///
/// The frame handler to process frames.
/// Cancellation token for the operation.
+ /// A task that runs until cancelled or the failure limit is exceeded.
public async Task RunAsync(IFrameHandler handler, CancellationToken ct)
{
var consecutiveFailures = 0;
@@ -233,7 +236,7 @@ public sealed class PipeServer : IDisposable
catch (Exception ex) { reason = ex.Message; return false; }
}
- /// Disposes the pipe server and cancels any pending operations.
+ ///
public void Dispose()
{
_cts.Cancel();
@@ -254,5 +257,6 @@ public interface IFrameHandler
/// The serialized message body.
/// The frame writer to send responses.
/// Cancellation token for the operation.
+ /// A task that completes when the frame has been handled and any response written.
Task HandleAsync(MessageKind kind, byte[] body, FrameWriter writer, CancellationToken ct);
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Program.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Program.cs
index db77d55d..6d569911 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Program.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Wonderware/Program.cs
@@ -120,6 +120,7 @@ public static class Program
/// set OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED=false to keep a read-only
/// deployment that still loads the SDK for reads.
///
+ /// The alarm-event writer, or null when alarm writes are disabled.
internal static IAlarmEventWriter? BuildAlarmWriter()
{
var raw = Environment.GetEnvironmentVariable("OTOPCUA_HISTORIAN_ALARM_WRITE_ENABLED");
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/DirectLogicAddress.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/DirectLogicAddress.cs
index 88c73903..cdbe8b8b 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/DirectLogicAddress.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/DirectLogicAddress.cs
@@ -29,6 +29,7 @@ public static class DirectLogicAddress
///
/// Input is null / empty / contains non-octal digits (8,9).
/// Parsed value exceeds ushort.MaxValue (0xFFFF).
+ /// The 0-based Modbus PDU address.
public static ushort UserVMemoryToPdu(string vAddress)
=> (ushort)DecodeOctalVAddress(vAddress); // DecodeOctalVAddress guards the 0xFFFF ceiling
@@ -80,11 +81,16 @@ public static class DirectLogicAddress
/// Octal 40400 == decimal 16640 (0x4100).
public const ushort SystemVMemoryOctalBase = 0x4100; // octal 40400 decoded
+ ///
+ /// Convert a 0-based offset within the system V-memory bank to its Modbus PDU address,
+ /// using the fixed system base at .
+ ///
///
/// 0-based register offset within the system bank. Pass 0 for V40400 itself; pass 1 for
/// V40401 (octal), and so on. NOT an octal-decoded value — the system bank lives at
/// consecutive PDU addresses, so the offset is plain decimal.
///
+ /// The 0-based Modbus PDU address for the system V-memory register.
public static ushort SystemVMemoryToPdu(ushort offsetWithinSystemBank)
{
var pdu = SystemVMemoryBasePdu + offsetWithinSystemBank;
@@ -109,6 +115,7 @@ public static class DirectLogicAddress
///
/// Input is null / empty / contains non-octal digits.
/// The result exceeds the 16-bit Modbus PDU range.
+ /// The 0-based Modbus PDU address, routed through the correct bank formula.
public static ushort VMemoryToPdu(string vAddress)
{
var octalValue = DecodeOctalVAddress(vAddress);
@@ -155,6 +162,7 @@ public static class DirectLogicAddress
/// ladder-logic editor's notation.
///
/// The Y-output address (octal, with optional Y prefix).
+ /// The 0-based Modbus coil address.
public static ushort YOutputToCoil(string yAddress) =>
AddOctalOffset(YOutputBaseCoil, StripPrefix(yAddress, 'Y'));
@@ -163,6 +171,7 @@ public static class DirectLogicAddress
/// 0-based Modbus coil address.
///
/// The C-relay address (octal, with optional C prefix).
+ /// The 0-based Modbus coil address.
public static ushort CRelayToCoil(string cAddress) =>
AddOctalOffset(CRelayBaseCoil, StripPrefix(cAddress, 'C'));
@@ -172,6 +181,7 @@ public static class DirectLogicAddress
/// exception — the CPU sizes the table to configured I/O, not installed modules.
///
/// The X-input address (octal, with optional X prefix).
+ /// The 0-based Modbus discrete-input address.
public static ushort XInputToDiscrete(string xAddress) =>
AddOctalOffset(XInputBaseDiscrete, StripPrefix(xAddress, 'X'));
@@ -180,6 +190,7 @@ public static class DirectLogicAddress
/// Modbus discrete-input address. Accepts "SP" prefix case-insensitively.
///
/// The SP special-relay address (octal, with optional SP prefix).
+ /// The 0-based Modbus discrete-input address.
public static ushort SpecialToDiscrete(string spAddress)
{
if (string.IsNullOrWhiteSpace(spAddress))
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/MelsecAddress.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/MelsecAddress.cs
index d3f272aa..b98ad45e 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/MelsecAddress.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/MelsecAddress.cs
@@ -53,6 +53,7 @@ public static class MelsecAddress
/// 0-based Modbus DI address the assignment-block has configured X0 to land at.
/// Typical default on QJ71MT91 sample projects: 0. Pass the site-specific value.
///
+ /// The 0-based Modbus discrete-input address.
public static ushort XInputToDiscrete(string xAddress, MelsecFamily family, ushort xBankBase = 0) =>
AddFamilyOffset(xBankBase, StripPrefix(xAddress, 'X'), family);
@@ -63,6 +64,7 @@ public static class MelsecAddress
/// MELSEC Y address. Y prefix optional, case-insensitive.
/// The PLC family — determines whether the trailing digits are hex or octal.
/// 0-based Modbus coil address the assignment-block has configured Y0 to land at.
+ /// The 0-based Modbus coil address.
public static ushort YOutputToCoil(string yAddress, MelsecFamily family, ushort yBankBase = 0) =>
AddFamilyOffset(yBankBase, StripPrefix(yAddress, 'Y'), family);
@@ -73,6 +75,7 @@ public static class MelsecAddress
///
/// MELSEC M address. M prefix optional, case-insensitive.
/// 0-based Modbus coil address the assignment-block has configured M0 to land at.
+ /// The 0-based Modbus coil address.
public static ushort MRelayToCoil(string mAddress, ushort mBankBase = 0)
{
var digits = StripPrefix(mAddress, 'M');
@@ -93,6 +96,7 @@ public static class MelsecAddress
///
/// MELSEC D address. D prefix optional, case-insensitive.
/// 0-based Modbus holding register address the assignment-block has configured D0 to land at.
+ /// The 0-based Modbus holding register address.
public static ushort DRegisterToHolding(string dAddress, ushort dBankBase = 0)
{
var digits = StripPrefix(dAddress, 'D');
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/ModbusModiconAddress.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/ModbusModiconAddress.cs
index 942e7a36..43801f18 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/ModbusModiconAddress.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Addressing/ModbusModiconAddress.cs
@@ -45,6 +45,7 @@ public static class ModbusModiconAddress
/// The parsed Modbus region, or default if parsing fails.
/// The zero-based PDU offset, or 0 if parsing fails.
/// The error message if parsing fails, or null on success.
+ /// true if the address was parsed successfully; false otherwise.
public static bool TryParse(string? address, out ModbusRegion region, out ushort offset, out string? error)
{
region = default;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriver.cs
index cd1ab6b2..9b300a3b 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriver.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriver.cs
@@ -135,6 +135,7 @@ public sealed class ModbusDriver
/// breaker without tripping siblings on the same TCP socket.
///
/// Tag reference to resolve the host for.
+ /// The per-slave host string used as the circuit-breaker key.
public string ResolveHost(string fullReference)
{
if (_tagsByName.TryGetValue(fullReference, out var tag))
@@ -171,14 +172,12 @@ public sealed class ModbusDriver
return true;
}
- /// Gets the unique identifier of this driver instance.
+ ///
public string DriverInstanceId => _driverInstanceId;
- /// Gets the driver type name.
+ ///
public string DriverType => "Modbus";
- /// Initializes the driver with the specified configuration JSON.
- /// JSON configuration string.
- /// Cancellation token.
+ ///
public async Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
WriteHealth(new DriverHealth(DriverState.Initializing, null, null));
@@ -212,17 +211,14 @@ public sealed class ModbusDriver
}
}
- /// Reinitializes the driver with new configuration.
- /// New JSON configuration string.
- /// Cancellation token.
+ ///
public async Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
await ShutdownAsync(cancellationToken);
await InitializeAsync(driverConfigJson, cancellationToken);
}
- /// Shuts down the driver and releases resources.
- /// Cancellation token.
+ ///
public async Task ShutdownAsync(CancellationToken cancellationToken)
{
var lastRead = ReadHealth().LastSuccessfulRead;
@@ -230,7 +226,7 @@ public sealed class ModbusDriver
WriteHealth(new DriverHealth(DriverState.Unknown, lastRead, null));
}
- /// Gets the current driver health status.
+ ///
public DriverHealth GetHealth() => ReadHealth();
///
@@ -245,17 +241,14 @@ public sealed class ModbusDriver
/// Driver.Modbus-003: barrier-protected publish of a new _health snapshot.
///
private void WriteHealth(DriverHealth value) => Volatile.Write(ref _health, value);
- /// Gets the memory footprint of the driver.
+ ///
public long GetMemoryFootprint() => 0;
- /// Flushes optional caches to free memory.
- /// Cancellation token.
+ ///
public Task FlushOptionalCachesAsync(CancellationToken cancellationToken) => Task.CompletedTask;
// ---- ITagDiscovery ----
- /// Discovers tags and builds the OPC UA address space.
- /// Address space builder.
- /// Cancellation token.
+ ///
public Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(builder);
@@ -277,9 +270,7 @@ public sealed class ModbusDriver
// ---- IReadable ----
- /// Reads the specified tag references from the Modbus device.
- /// Tag references to read.
- /// Cancellation token.
+ ///
public async Task> ReadAsync(
IReadOnlyList fullReferences, CancellationToken cancellationToken)
{
@@ -537,6 +528,7 @@ public sealed class ModbusDriver
/// on coalesced-read failure (#148), narrowed by bisection (#150), cleared by the
/// re-probe loop (#151) when ranges become healthy again.
///
+ /// A read-only list of currently auto-prohibited Modbus ranges.
public IReadOnlyList GetAutoProhibitedRanges()
{
lock (_autoProhibitedLock)
@@ -587,6 +579,7 @@ public sealed class ModbusDriver
/// retry (single-register or already-narrowed).
///
/// Cancellation token.
+ /// A task that represents the asynchronous operation.
internal async Task RunReprobeOnceForTestAsync(CancellationToken ct)
{
var transport = _transport ?? throw new InvalidOperationException("Transport not connected");
@@ -920,9 +913,7 @@ public sealed class ModbusDriver
// ---- IWritable ----
- /// Writes values to the specified tag references on the Modbus device.
- /// Write requests to execute.
- /// Cancellation token.
+ ///
public async Task> WriteAsync(
IReadOnlyList writes, CancellationToken cancellationToken)
{
@@ -1160,17 +1151,12 @@ public sealed class ModbusDriver
// ---- ISubscribable (polling overlay via shared engine) ----
- /// Subscribes to value changes on the specified tag references.
- /// Tag references to subscribe to.
- /// Interval for publishing changes.
- /// Cancellation token.
+ ///
public Task SubscribeAsync(
IReadOnlyList fullReferences, TimeSpan publishingInterval, CancellationToken cancellationToken) =>
Task.FromResult(_poll.Subscribe(fullReferences, publishingInterval));
- /// Unsubscribes from value changes using the specified handle.
- /// Subscription handle.
- /// Cancellation token.
+ ///
public Task UnsubscribeAsync(ISubscriptionHandle handle, CancellationToken cancellationToken)
{
_poll.Unsubscribe(handle);
@@ -1179,7 +1165,7 @@ public sealed class ModbusDriver
// ---- IHostConnectivityProbe ----
- /// Gets the current connectivity status for all hosts.
+ ///
public IReadOnlyList GetHostStatuses()
{
lock (_probeLock)
@@ -1246,6 +1232,7 @@ public sealed class ModbusDriver
/// from 2 chars per register).
///
/// Tag definition to measure.
+ /// The number of 16-bit registers the tag occupies.
internal static ushort RegisterCount(ModbusTagDefinition tag) => tag.DataType switch
{
ModbusDataType.Int16 or ModbusDataType.UInt16 or ModbusDataType.BitInRegister or ModbusDataType.Bcd16 => 1,
@@ -1306,6 +1293,7 @@ public sealed class ModbusDriver
/// Decodes a register value according to the tag's data type.
/// Raw register bytes.
/// Tag definition specifying the data type.
+ /// The decoded value as a boxed .NET type.
internal static object DecodeRegister(ReadOnlySpan data, ModbusTagDefinition tag)
{
switch (tag.DataType)
@@ -1387,6 +1375,7 @@ public sealed class ModbusDriver
/// Encodes a value into register bytes according to the tag's data type.
/// Value to encode.
/// Tag definition specifying the data type.
+ /// The encoded register bytes.
internal static byte[] EncodeRegister(object? value, ModbusTagDefinition tag)
{
switch (tag.DataType)
@@ -1522,6 +1511,7 @@ public sealed class ModbusDriver
///
/// Raw BCD value.
/// Number of nibbles to decode.
+ /// The decoded decimal value.
internal static uint DecodeBcd(uint raw, int nibbles)
{
uint result = 0;
@@ -1542,6 +1532,7 @@ public sealed class ModbusDriver
///
/// Decimal value to encode.
/// Number of nibbles to encode.
+ /// The BCD-encoded value.
internal static uint EncodeBcd(uint value, int nibbles)
{
uint result = 0;
@@ -1576,6 +1567,7 @@ public sealed class ModbusDriver
/// extensions.
///
/// Modbus exception code.
+ /// The corresponding OPC UA status code.
internal static uint MapModbusExceptionToStatus(byte exceptionCode) => exceptionCode switch
{
0x01 => StatusBadNotSupported, // Illegal Function — FC not in supported list
@@ -1596,6 +1588,7 @@ public sealed class ModbusDriver
/// leak the probe loop, re-probe loop, and poll-engine background tasks. Shares
/// with to keep them in sync.
///
+ /// A task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
await TeardownAsync().ConfigureAwait(false);
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriverFactoryExtensions.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriverFactoryExtensions.cs
index 392cc5d1..113e7b47 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriverFactoryExtensions.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriverFactoryExtensions.cs
@@ -33,6 +33,7 @@ public static class ModbusDriverFactoryExtensions
/// Public for the Server-side bootstrapper + test consumers (Admin.Tests, etc.).
/// The unique identifier for the driver instance.
/// The JSON configuration string for the driver.
+ /// A configured instance.
public static ModbusDriver CreateInstance(string driverInstanceId, string driverConfigJson)
=> CreateInstance(driverInstanceId, driverConfigJson, loggerFactory: null);
@@ -40,6 +41,7 @@ public static class ModbusDriverFactoryExtensions
/// The unique identifier for the driver instance.
/// The JSON configuration string for the driver.
/// Optional logger factory for creating loggers per driver instance.
+ /// A configured instance.
public static ModbusDriver CreateInstance(string driverInstanceId, string driverConfigJson, ILoggerFactory? loggerFactory)
{
ArgumentException.ThrowIfNullOrWhiteSpace(driverInstanceId);
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusTcpTransport.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusTcpTransport.cs
index f317af5d..772e1a8a 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusTcpTransport.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusTcpTransport.cs
@@ -63,8 +63,7 @@ public sealed class ModbusTcpTransport : IModbusTransport
_reconnect = reconnect ?? new ModbusReconnectOptions();
}
- /// Connects to the Modbus TCP server with IPv4 preference.
- /// The cancellation token for the operation.
+ ///
public async Task ConnectAsync(CancellationToken ct)
{
// Resolve the host explicitly + prefer IPv4. .NET's TcpClient default-constructor is
@@ -121,16 +120,14 @@ public sealed class ModbusTcpTransport : IModbusTransport
/// keep-alive timing into "use the default" on most OSes.
///
/// The timespan to clamp to whole seconds.
+ /// The number of whole seconds, with a minimum of 1.
internal static int ClampToWholeSeconds(TimeSpan ts)
{
var seconds = (int)Math.Ceiling(ts.TotalSeconds);
return seconds < 1 ? 1 : seconds;
}
- /// Sends a Modbus PDU and returns the response, with automatic retry on socket failure.
- /// The Modbus unit/slave ID.
- /// The protocol data unit to send.
- /// The cancellation token for the operation.
+ ///
public async Task SendAsync(byte unitId, byte[] pdu, CancellationToken ct)
{
if (_disposed) throw new ObjectDisposedException(nameof(ModbusTcpTransport));
@@ -284,6 +281,7 @@ public sealed class ModbusTcpTransport : IModbusTransport
}
/// Asynchronously disposes the transport and underlying socket resources.
+ /// A value task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
if (_disposed) return;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/OpcUaClientBrowseSession.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/OpcUaClientBrowseSession.cs
index ef9dacaa..01e54ce5 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/OpcUaClientBrowseSession.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/OpcUaClientBrowseSession.cs
@@ -32,25 +32,17 @@ internal sealed class OpcUaClientBrowseSession : IBrowseSession
_rootNodeId = rootNodeId;
}
- /// Opaque token identifying this session in the AdminUI registry.
+ ///
public Guid Token { get; } = Guid.NewGuid();
- /// Wall-clock time of the most recent successful browse call; the reaper uses
- /// this for idle eviction.
+ ///
public DateTime LastUsedUtc { get; private set; } = DateTime.UtcNow;
- /// Browse one level under the configured root node.
- /// Cancellation token.
+ ///
public Task> RootAsync(CancellationToken cancellationToken)
=> BrowseOneLevelAsync(_rootNodeId, cancellationToken);
- /// Browse one level under the node identified by ,
- /// which must be a stable reference produced by
- /// (or a plain ns=N;… form).
- /// Stable reference string for the parent node.
- /// Cancellation token.
- /// Thrown when cannot be
- /// resolved against the live session's namespace table.
+ ///
public Task> ExpandAsync(string nodeId, CancellationToken cancellationToken)
{
if (!NamespaceMap.TryResolve(_session, nodeId, out var resolved))
@@ -59,10 +51,7 @@ internal sealed class OpcUaClientBrowseSession : IBrowseSession
return BrowseOneLevelAsync(resolved, cancellationToken);
}
- /// The OPC UA picker treats variables as terminal leaves and does not surface
- /// a per-attribute side-panel, so this always returns empty.
- /// Ignored.
- /// Ignored.
+ ///
public Task> AttributesAsync(string nodeId, CancellationToken cancellationToken)
=> Task.FromResult>(Array.Empty());
@@ -158,6 +147,7 @@ internal sealed class OpcUaClientBrowseSession : IBrowseSession
/// Idempotent best-effort dispose: closes the underlying session if it's a
/// concrete , disposes it, and disposes the gate. Close errors are
/// swallowed because the registry reaper may be racing a remote disconnect.
+ /// A value task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
if (_disposed) return;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/OpcUaClientDriverBrowser.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/OpcUaClientDriverBrowser.cs
index dd0a0e64..aedf9080 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/OpcUaClientDriverBrowser.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/OpcUaClientDriverBrowser.cs
@@ -31,13 +31,10 @@ public sealed class OpcUaClientDriverBrowser : IDriverBrowser
_logger = logger ?? NullLogger.Instance;
}
- /// Driver type key — matches the AdminUI's persisted "OpcUaClient" value.
+ ///
public string DriverType => "OpcUaClient";
- /// Opens a transient OPC UA session and returns a browse session over it.
- /// Driver options serialized as JSON; same shape the runtime
- /// driver would consume.
- /// Cancellation for the connect phase only.
+ ///
public async Task OpenAsync(string configJson, CancellationToken cancellationToken)
{
var opts = JsonSerializer.Deserialize(configJson, JsonOpts)
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts/NamespaceMap.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts/NamespaceMap.cs
index 82ab003f..67c110f7 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts/NamespaceMap.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts/NamespaceMap.cs
@@ -48,6 +48,7 @@ public sealed class NamespaceMap
/// Snapshot the namespace table from a live session.
/// The OPC UA session to snapshot.
+ /// A new capturing the session's current namespace table.
public static NamespaceMap FromSession(ISession session)
{
ArgumentNullException.ThrowIfNull(session);
@@ -60,6 +61,7 @@ public sealed class NamespaceMap
/// a live .
///
/// The namespace table to snapshot.
+ /// A new capturing the supplied namespace table.
public static NamespaceMap FromTable(NamespaceTable namespaceUris)
{
ArgumentNullException.ThrowIfNull(namespaceUris);
@@ -71,11 +73,13 @@ public sealed class NamespaceMap
/// The namespace URI at the given index, or null if out of range.
/// The zero-based index in the namespace table.
+ /// The namespace URI string, or if is out of range.
public string? UriForIndex(int index) =>
index >= 0 && index < _uris.Length ? _uris[index] : null;
/// The index for a namespace URI, or null if the URI is not in the table.
/// The namespace URI to look up.
+ /// The zero-based index, or if the URI is not present.
public ushort? IndexForUri(string uri) =>
_uriToIndex.TryGetValue(uri, out var idx) ? idx : null;
@@ -87,6 +91,7 @@ public sealed class NamespaceMap
/// address space so it survives a remote namespace-table reorder.
///
/// The NodeId to render as a stable reference.
+ /// A stable nsu=… reference string, or the raw node ID form for namespace 0 or unknown namespaces.
public string ToStableReference(NodeId nodeId)
{
ArgumentNullException.ThrowIfNull(nodeId);
@@ -115,6 +120,7 @@ public sealed class NamespaceMap
/// The OPC UA session whose namespace table to resolve against.
/// The reference string to resolve (either nsu=… or ns=N;… format).
/// On success, the resolved NodeId; otherwise NodeId.Null.
+ /// if the reference was resolved to a non-null NodeId; otherwise .
public static bool TryResolve(ISession currentSession, string reference, out NodeId nodeId)
{
nodeId = NodeId.Null;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient/OpcUaClientDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient/OpcUaClientDriver.cs
index d81ed3b7..651f8b25 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient/OpcUaClientDriver.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient/OpcUaClientDriver.cs
@@ -32,6 +32,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
{
private readonly ILogger _logger;
+ /// Initializes a new instance of with the given options and instance ID.
/// Driver configuration.
/// Stable logical ID from the config DB.
/// Optional logger; defaults to NullLogger when not supplied.
@@ -121,14 +122,12 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
///
private NamespaceMap? _namespaceMap;
- /// Gets the stable logical identifier for this driver instance from the config database.
+ ///
public string DriverInstanceId => _driverInstanceId;
- /// Gets the driver type identifier.
+ ///
public string DriverType => "OpcUaClient";
- /// Initializes the OPC UA client driver with the given configuration.
- /// JSON-serialized driver configuration.
- /// Cancellation token for the operation.
+ ///
public async Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
_health = new DriverHealth(DriverState.Initializing, null, null);
@@ -303,6 +302,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// existing single-endpoint configs keep working without migration.
///
/// Driver options containing endpoint configuration.
+ /// An ordered list of endpoint URL candidates for connection failover.
internal static IReadOnlyList ResolveEndpointCandidates(OpcUaClientDriverOptions opts)
{
if (opts.EndpointUrls is { Count: > 0 }) return opts.EndpointUrls;
@@ -352,6 +352,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// private key N times, wasteful + keeps the password in memory longer.
///
/// Driver options containing authentication configuration.
+ /// A configured for the requested authentication type.
internal static UserIdentity BuildUserIdentity(OpcUaClientDriverOptions options) =>
options.AuthType switch
{
@@ -455,6 +456,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// challenge during session activation).
///
/// Driver options containing certificate configuration.
+ /// A backed by the loaded client user certificate.
internal static UserIdentity BuildCertificateIdentity(OpcUaClientDriverOptions options)
{
if (string.IsNullOrWhiteSpace(options.UserCertificatePath))
@@ -482,6 +484,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// Convert a driver to the OPC UA policy URI.
/// The driver security policy to map.
+ /// The OPC UA security policy URI string corresponding to the given policy.
internal static string MapSecurityPolicy(OpcUaSecurityPolicy policy) => policy switch
{
OpcUaSecurityPolicy.None => SecurityPolicies.None,
@@ -496,17 +499,14 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
private static string ShortPolicyName(string policyUri) =>
policyUri?.Substring(policyUri.LastIndexOf('#') + 1) ?? "(null)";
- /// Reinitializes the driver with new configuration, shutting down and restarting the session.
- /// JSON-serialized driver configuration.
- /// Cancellation token for the operation.
+ ///
public async Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
await ShutdownAsync(cancellationToken).ConfigureAwait(false);
await InitializeAsync(driverConfigJson, cancellationToken).ConfigureAwait(false);
}
- /// Gracefully shuts down the OPC UA session, unsubscribing all active monitoring items and closing the connection.
- /// Cancellation token for the operation.
+ ///
public async Task ShutdownAsync(CancellationToken cancellationToken)
{
// Tear down remote subscriptions first — otherwise Session.Close will try and may fail
@@ -582,7 +582,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
}
- /// Gets the current health status of the OPC UA client driver.
+ ///
public DriverHealth GetHealth() => _health;
///
@@ -594,6 +594,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// 10k-node remote server reports ~5 MB — well within the budget and detectable by the
/// Core slope alarm (Driver.OpcUaClient-013).
///
+ /// Approximate in-driver memory usage in bytes based on the discovered node count.
public long GetMemoryFootprint() => _discoveredNodeCount * 512L;
///
@@ -604,6 +605,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// will rebuild it cleanly from the remote server.
///
/// Cancellation token for the operation.
+ /// A task that represents the asynchronous operation.
public Task FlushOptionalCachesAsync(CancellationToken cancellationToken)
{
_discoveredNodeCount = 0;
@@ -612,9 +614,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
// ---- IReadable ----
- /// Reads the current values of the specified nodes from the remote OPC UA server.
- /// Fully-qualified node identifiers to read.
- /// Cancellation token for the operation.
+ ///
public async Task> ReadAsync(
IReadOnlyList fullReferences, CancellationToken cancellationToken)
{
@@ -703,9 +703,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
// ---- IWritable ----
- /// Writes values to the specified nodes on the remote OPC UA server.
- /// Write requests specifying nodes and values to write.
- /// Cancellation token for the operation.
+ ///
public async Task> WriteAsync(
IReadOnlyList writes, CancellationToken cancellationToken)
{
@@ -801,6 +799,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// The OPC UA session to resolve the node ID against.
/// The full reference string to parse.
/// The parsed node ID when successful.
+ /// if the reference was parsed to a valid node ID; otherwise.
internal static bool TryParseNodeId(ISession session, string fullReference, out NodeId nodeId) =>
NamespaceMap.TryResolve(session, fullReference, out nodeId);
@@ -817,9 +816,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
// ---- ITagDiscovery ----
- /// Discovers the remote OPC UA server's address space and materializes it through the supplied builder.
- /// Address space builder for materializing discovered nodes.
- /// Cancellation token for the operation.
+ ///
public async Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(builder);
@@ -1086,6 +1083,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// StatusCode + timestamps.
///
/// The OPC UA data type NodeId to map.
+ /// The corresponding to the given OPC UA data type.
internal static DriverDataType MapUpstreamDataType(NodeId dataType)
{
if (dataType == DataTypeIds.Boolean) return DriverDataType.Boolean;
@@ -1114,6 +1112,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// ; read-only as .
///
/// The OPC UA access level bitmask.
+ /// The corresponding to the given access level.
internal static SecurityClassification MapAccessLevelToSecurityClass(byte accessLevel)
{
const byte CurrentWrite = 2; // AccessLevels.CurrentWrite = 0x02
@@ -1124,10 +1123,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
// ---- ISubscribable ----
- /// Subscribes to monitored value changes on the specified nodes from the remote OPC UA server.
- /// Fully-qualified node identifiers to monitor.
- /// Desired minimum interval between publish cycles.
- /// Cancellation token for the operation.
+ ///
public async Task SubscribeAsync(
IReadOnlyList fullReferences, TimeSpan publishingInterval, CancellationToken cancellationToken)
{
@@ -1198,9 +1194,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
return handle;
}
- /// Unsubscribes from monitored value changes for the specified subscription handle.
- /// The subscription handle to unsubscribe.
- /// Cancellation token for the operation.
+ ///
public async Task UnsubscribeAsync(ISubscriptionHandle handle, CancellationToken cancellationToken)
{
if (handle is not OpcUaSubscriptionHandle h) return;
@@ -1272,7 +1266,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
private sealed record OpcUaSubscriptionHandle(long Id) : ISubscriptionHandle
{
- /// Gets the diagnostic identifier for this subscription.
+ ///
public string DiagnosticId => $"opcua-sub-{Id}";
}
@@ -1290,9 +1284,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
private const int AlarmFieldTime = 5;
private const int AlarmFieldConditionId = 6;
- /// Subscribes to alarm and event notifications from the remote OPC UA server.
- /// Source node identifiers to subscribe alarms from.
- /// Cancellation token for the operation.
+ ///
public async Task SubscribeAlarmsAsync(
IReadOnlyList sourceNodeIds, CancellationToken cancellationToken)
{
@@ -1378,9 +1370,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
return handle;
}
- /// Unsubscribes from alarm and event notifications for the specified alarm subscription handle.
- /// The alarm subscription handle to unsubscribe.
- /// Cancellation token for the operation.
+ ///
public async Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken)
{
if (handle is not OpcUaAlarmSubscriptionHandle h) return;
@@ -1400,9 +1390,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
finally { _gate.Release(); }
}
- /// Acknowledges multiple alarms by calling the remote OPC UA server's Acknowledge method.
- /// List of alarm acknowledgement requests.
- /// Cancellation token for the operation.
+ ///
public async Task AcknowledgeAsync(
IReadOnlyList acknowledgements, CancellationToken cancellationToken)
{
@@ -1517,6 +1505,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// guidance: 1-200 Low, 201-500 Medium, 501-800 High, 801-1000 Critical.
///
/// The OPC UA severity value (1-1000).
+ /// The coarse-grained bucket for the given OPC UA severity.
internal static AlarmSeverity MapSeverity(ushort opcSeverity) => opcSeverity switch
{
<= 200 => AlarmSeverity.Low,
@@ -1539,18 +1528,13 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
private sealed record OpcUaAlarmSubscriptionHandle(long Id) : IAlarmSubscriptionHandle
{
- /// Gets the diagnostic identifier for this alarm subscription.
+ ///
public string DiagnosticId => $"opcua-alarm-sub-{Id}";
}
// ---- IHistoryProvider (passthrough to upstream server) ----
- /// Reads raw historical data from the remote OPC UA server.
- /// Fully-qualified node identifier to read history for.
- /// Start time in UTC for the history query.
- /// End time in UTC for the history query.
- /// Maximum number of values to return.
- /// Cancellation token for the operation.
+ ///
public async Task ReadRawAsync(
string fullReference, DateTime startUtc, DateTime endUtc, uint maxValuesPerNode,
CancellationToken cancellationToken)
@@ -1567,13 +1551,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
.ConfigureAwait(false);
}
- /// Reads processed (aggregated) historical data from the remote OPC UA server.
- /// Fully-qualified node identifier to read history for.
- /// Start time in UTC for the history query.
- /// End time in UTC for the history query.
- /// Time interval for aggregation.
- /// The aggregation function to apply.
- /// Cancellation token for the operation.
+ ///
public async Task ReadProcessedAsync(
string fullReference, DateTime startUtc, DateTime endUtc, TimeSpan interval,
HistoryAggregateType aggregate, CancellationToken cancellationToken)
@@ -1590,10 +1568,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
.ConfigureAwait(false);
}
- /// Reads historical data at specific timestamps from the remote OPC UA server.
- /// Fully-qualified node identifier to read history for.
- /// List of specific timestamps to read values at.
- /// Cancellation token for the operation.
+ ///
public async Task ReadAtTimeAsync(
string fullReference, IReadOnlyList timestampsUtc, CancellationToken cancellationToken)
{
@@ -1665,6 +1640,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
/// Map to the OPC UA Part 13 standard aggregate NodeId.
/// The aggregation function type to map.
+ /// The OPC UA aggregate function NodeId corresponding to the given aggregate type.
internal static NodeId MapAggregateToNodeId(HistoryAggregateType aggregate) => aggregate switch
{
HistoryAggregateType.Average => ObjectIds.AggregateFunction_Average,
@@ -1694,7 +1670,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
?? ResolveEndpointCandidates(_options).FirstOrDefault()
?? _options.EndpointUrl;
- /// Gets the current connectivity status of the remote OPC UA server host.
+ ///
public IReadOnlyList GetHostStatuses()
{
lock (_probeLock)
@@ -1927,6 +1903,7 @@ public sealed class OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWrit
}
/// Asynchronously disposes the driver and releases all associated resources.
+ /// A task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
if (_disposed) return;
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7CpuTypeMap.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7CpuTypeMap.cs
index 9f591094..8de3c279 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7CpuTypeMap.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7CpuTypeMap.cs
@@ -4,6 +4,9 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.S7;
internal static class S7CpuTypeMap
{
+ /// Maps an enum value to the equivalent S7.Net .
+ /// The S7 CPU type to convert.
+ /// The corresponding value.
public static S7NetCpuType ToS7Net(S7CpuType type) => type switch
{
S7CpuType.S7200 => S7NetCpuType.S7200,
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7Driver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7Driver.cs
index 312144dc..c63636f5 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7Driver.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7/S7Driver.cs
@@ -103,15 +103,12 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
private DriverHealth _health = new(DriverState.Unknown, null, null);
private bool _disposed;
- /// Gets the unique driver instance identifier.
+ ///
public string DriverInstanceId => driverInstanceId;
- /// Gets the driver type name.
+ ///
public string DriverType => "S7";
- /// Initializes the driver with the provided configuration.
- /// JSON configuration string.
- /// Cancellation token.
- /// A task representing the asynchronous operation.
+ ///
public async Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
_health = new DriverHealth(DriverState.Initializing, null, null);
@@ -192,10 +189,7 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
}
}
- /// Reinitializes the driver with a new configuration.
- /// JSON configuration string.
- /// Cancellation token.
- /// A task representing the asynchronous operation.
+ ///
public async Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
// InitializeAsync re-parses driverConfigJson, so a config change delivered here is
@@ -204,9 +198,7 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
await InitializeAsync(driverConfigJson, cancellationToken).ConfigureAwait(false);
}
- /// Shuts down the driver and releases resources.
- /// Cancellation token.
- /// A task representing the asynchronous operation.
+ ///
public async Task ShutdownAsync(CancellationToken cancellationToken)
{
// Signal cancellation to the probe + poll loops first, collect their Task handles,
@@ -251,13 +243,10 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
}
- /// Gets the current driver health.
- /// The current health state.
+ ///
public DriverHealth GetHealth() => _health;
- /// Flushes optional caches to free memory.
- /// Cancellation token.
- /// A task representing the asynchronous operation.
+ ///
public Task FlushOptionalCachesAsync(CancellationToken cancellationToken) => Task.CompletedTask;
///
@@ -338,14 +327,12 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
/// under 4 KB; return 0 because the contract asks for a
/// driver-attributable growth number and S7.Net doesn't expose one.
///
+ /// Zero, as S7.Net does not expose a queryable memory footprint.
public long GetMemoryFootprint() => 0;
// ---- IReadable ----
- /// Reads values from the specified tag references.
- /// Tag references to read.
- /// Cancellation token.
- /// A task representing the asynchronous operation returning a list of data value snapshots.
+ ///
public async Task> ReadAsync(
IReadOnlyList fullReferences, CancellationToken cancellationToken)
{
@@ -457,10 +444,7 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
// ---- IWritable ----
- /// Writes values to the specified tags.
- /// Write requests containing tag references and values.
- /// Cancellation token.
- /// A task representing the asynchronous operation returning a list of write results.
+ ///
public async Task> WriteAsync(
IReadOnlyList writes, CancellationToken cancellationToken)
{
@@ -597,10 +581,7 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
// ---- ITagDiscovery ----
- /// Discovers tags and builds the OPC UA address space.
- /// Address space builder.
- /// Cancellation token.
- /// A task representing the asynchronous operation.
+ ///
public Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(builder);
@@ -638,11 +619,7 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
// ---- ISubscribable (polling overlay) ----
- /// Subscribes to changes on the specified tag references.
- /// Tag references to subscribe to.
- /// Polling interval.
- /// Cancellation token.
- /// A task representing the asynchronous operation returning a subscription handle.
+ ///
public Task SubscribeAsync(
IReadOnlyList fullReferences, TimeSpan publishingInterval, CancellationToken cancellationToken)
{
@@ -662,10 +639,7 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
return Task.FromResult(handle);
}
- /// Unsubscribes from a subscription.
- /// Subscription handle.
- /// Cancellation token.
- /// A task representing the asynchronous operation.
+ ///
public Task UnsubscribeAsync(ISubscriptionHandle handle, CancellationToken cancellationToken)
{
if (handle is S7SubscriptionHandle h && _subscriptions.TryRemove(h.Id, out var state))
@@ -812,7 +786,7 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
private sealed record S7SubscriptionHandle(long Id) : ISubscriptionHandle
{
- /// Gets the diagnostic identifier for this subscription.
+ ///
public string DiagnosticId => $"s7-sub-{Id}";
}
@@ -825,8 +799,7 @@ public sealed class S7Driver(S7DriverOptions options, string driverInstanceId, I
///
public string HostName => $"{_options.Host}:{_options.Port}";
- /// Gets the host connectivity statuses.
- /// A list containing the current host status.
+ ///
public IReadOnlyList GetHostStatuses()
{
lock (_probeLock)
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/ITwinCATClient.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/ITwinCATClient.cs
index 03a12b4b..6b0eba9a 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/ITwinCATClient.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/ITwinCATClient.cs
@@ -17,6 +17,7 @@ public interface ITwinCATClient : IDisposable
/// The target AMS address.
/// The connection timeout.
/// Cancellation token for the connection attempt.
+ /// A task that represents the asynchronous operation.
Task ConnectAsync(TwinCATAmsAddress address, TimeSpan timeout, CancellationToken cancellationToken);
/// True when the AMS router + target both accept commands.
@@ -41,6 +42,7 @@ public interface ITwinCATClient : IDisposable
/// The target data type.
/// Optional bit index for bit extraction within a word.
/// Cancellation token for the read operation.
+ /// A tuple of the boxed value (or null) and the mapped OPC UA status code.
Task<(object? value, uint status)> ReadValueAsync(
string symbolPath,
TwinCATDataType type,
@@ -56,6 +58,7 @@ public interface ITwinCATClient : IDisposable
/// Optional bit index for bit manipulation within a word.
/// The value to write.
/// Cancellation token for the write operation.
+ /// The mapped OPC UA status code (0 = Good).
Task WriteValueAsync(
string symbolPath,
TwinCATDataType type,
@@ -68,6 +71,7 @@ public interface ITwinCATClient : IDisposable
/// Used by 's probe loop.
///
/// Cancellation token for the probe operation.
+ /// true when the target's AMS state is reachable; otherwise false.
Task ProbeAsync(CancellationToken cancellationToken);
///
@@ -85,6 +89,7 @@ public interface ITwinCATClient : IDisposable
/// immediately (Driver.TwinCAT-014).
/// Invoked with (symbolPath, boxedValue) per notification.
/// Cancels the initial registration; does not tear down an established notification.
+ /// An opaque handle whose tears the notification down.
Task AddNotificationAsync(
string symbolPath,
TwinCATDataType type,
@@ -102,6 +107,7 @@ public interface ITwinCATClient : IDisposable
/// decide whether to drill in via their own walker.
///
/// Cancellation token for the enumeration operation.
+ /// An async sequence of discovered symbols from the target's symbol table.
IAsyncEnumerable BrowseSymbolsAsync(CancellationToken cancellationToken);
}
@@ -125,5 +131,6 @@ public sealed record TwinCATDiscoveredSymbol(
public interface ITwinCATClientFactory
{
/// Creates a new TwinCAT client instance.
+ /// A new instance.
ITwinCATClient Create();
}
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriver.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriver.cs
index 89feddc4..e3cfe5ec 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriver.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriver.cs
@@ -56,15 +56,12 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
OnDataChange?.Invoke(this, new DataChangeEventArgs(handle, tagRef, snapshot)));
}
- /// Gets the unique driver instance identifier.
+ ///
public string DriverInstanceId => _driverInstanceId;
- /// Gets the driver type name.
+ ///
public string DriverType => "TwinCAT";
- /// Initializes the driver with configuration and establishes device connections.
- /// JSON configuration string for the driver.
- /// Cancellation token.
- /// Completion task.
+ ///
public Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
_health = new DriverHealth(DriverState.Initializing, null, null);
@@ -109,19 +106,14 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
return Task.CompletedTask;
}
- /// Reinitializes the driver by shutting down and reinitializing with new configuration.
- /// JSON configuration string for the driver.
- /// Cancellation token.
- /// Completion task.
+ ///
public async Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
await ShutdownAsync(cancellationToken).ConfigureAwait(false);
await InitializeAsync(driverConfigJson, cancellationToken).ConfigureAwait(false);
}
- /// Shuts down the driver and releases all device connections and subscriptions.
- /// Cancellation token.
- /// Completion task.
+ ///
public async Task ShutdownAsync(CancellationToken cancellationToken)
{
// Native subs first — disposing the handles is cheap + lets the client close its
@@ -154,8 +146,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
}
- /// Gets the current driver health status.
- /// Driver health information.
+ ///
public DriverHealth GetHealth() => _health;
///
@@ -165,6 +156,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
/// ~256 bytes per pre-declared tag (tag-definition record + dictionary overhead) and
/// ~512 bytes per active native subscription.
///
+ /// The estimated memory usage in bytes attributable to this driver instance.
public long GetMemoryFootprint() =>
(_tagsByName.Count * 256L) + (_nativeSubs.Count * 512L);
@@ -187,10 +179,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
// ---- IReadable ----
- /// Reads values for the specified tag references from ADS devices.
- /// The full tag references to read.
- /// Cancellation token.
- /// Data value snapshots for each reference.
+ ///
public async Task> ReadAsync(
IReadOnlyList fullReferences, CancellationToken cancellationToken)
{
@@ -245,10 +234,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
// ---- IWritable ----
- /// Writes values to the specified tags on ADS devices.
- /// The write requests to execute.
- /// Cancellation token.
- /// Write results for each request.
+ ///
public async Task> WriteAsync(
IReadOnlyList writes, CancellationToken cancellationToken)
{
@@ -309,10 +295,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
// ---- ITagDiscovery ----
- /// Discovers devices and tags from ADS configuration and optionally controller symbols.
- /// Address space builder for adding discovered nodes.
- /// Cancellation token.
- /// Completion task.
+ ///
public async Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(builder);
@@ -447,10 +430,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
return handle;
}
- /// Unsubscribes from a native or poll-based subscription.
- /// The subscription handle to unsubscribe.
- /// Cancellation token.
- /// Completion task.
+ ///
public Task UnsubscribeAsync(ISubscriptionHandle handle, CancellationToken cancellationToken)
{
if (handle is NativeSubscriptionHandle native && _nativeSubs.TryRemove(native.Id, out var sub))
@@ -464,7 +444,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
private sealed record NativeSubscriptionHandle(long Id) : ISubscriptionHandle
{
- /// Gets the diagnostic identifier for the subscription.
+ ///
public string DiagnosticId => $"twincat-native-sub-{Id}";
}
@@ -474,8 +454,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
// ---- IHostConnectivityProbe ----
- /// Gets the connectivity status for all configured devices.
- /// List of host connectivity statuses.
+ ///
public IReadOnlyList GetHostStatuses() =>
[.. _devices.Values.Select(s => new HostConnectivityStatus(s.Options.HostAddress, s.HostState, s.HostStateChangedUtc))];
@@ -536,9 +515,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
///
public const string UnresolvedHostSentinel = "";
- /// Resolves the device host address for the specified tag reference.
- /// The full tag reference.
- /// The host address or if not found.
+ ///
public string ResolveHost(string fullReference)
{
if (_tagsByName.TryGetValue(fullReference, out var def))
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriverFactoryExtensions.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriverFactoryExtensions.cs
index 72430816..0195f04b 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriverFactoryExtensions.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATDriverFactoryExtensions.cs
@@ -24,6 +24,7 @@ public static class TwinCATDriverFactoryExtensions
/// Creates a TwinCAT driver instance from the provided configuration.
/// The driver instance identifier.
/// The driver configuration as JSON.
+ /// A new configured from the supplied JSON.
internal static TwinCATDriver CreateInstance(string driverInstanceId, string driverConfigJson)
{
ArgumentException.ThrowIfNullOrWhiteSpace(driverInstanceId);
@@ -39,6 +40,7 @@ public static class TwinCATDriverFactoryExtensions
///
/// The JSON configuration string.
/// The driver instance identifier.
+ /// The parsed .
internal static TwinCATDriverOptions ParseOptions(string driverConfigJson, string driverInstanceId)
{
ArgumentException.ThrowIfNullOrWhiteSpace(driverConfigJson);
@@ -79,6 +81,7 @@ public static class TwinCATDriverFactoryExtensions
///
/// The JSON configuration string.
/// The driver instance identifier.
+ /// The parsed .
public static TwinCATDriverOptions ParseOptionsForTests(string driverConfigJson, string driverInstanceId)
=> ParseOptions(driverConfigJson, driverInstanceId);
diff --git a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATSystemSymbolFilter.cs b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATSystemSymbolFilter.cs
index 7db22b59..9be270f0 100644
--- a/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATSystemSymbolFilter.cs
+++ b/src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.TwinCAT/TwinCATSystemSymbolFilter.cs
@@ -10,6 +10,7 @@ public static class TwinCATSystemSymbolFilter
{
/// Gets a value indicating whether a symbol is a system or infrastructure symbol.
/// The symbol instance path to check.
+ /// when the symbol is a TwinCAT system or infrastructure symbol; otherwise .
public static bool IsSystemSymbol(string instancePath)
{
if (string.IsNullOrWhiteSpace(instancePath)) return true;
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/BrowseSessionReaper.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/BrowseSessionReaper.cs
index cffe77a6..96f61753 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/BrowseSessionReaper.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/BrowseSessionReaper.cs
@@ -38,6 +38,8 @@ public sealed class BrowseSessionReaper(
/// Evicts every session whose
/// is older than . Internal so tests can drive a tick directly.
+ /// Cancellation token for the reap operation.
+ /// A task that represents the asynchronous operation.
internal async Task ReapOnceAsync(CancellationToken ct)
{
var now = DateTime.UtcNow;
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/BrowseSessionRegistry.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/BrowseSessionRegistry.cs
index ca6feee9..112b8fb7 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/BrowseSessionRegistry.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/BrowseSessionRegistry.cs
@@ -14,17 +14,25 @@ public sealed class BrowseSessionRegistry
private readonly ConcurrentDictionary _sessions = new();
/// Adds (or replaces) a session in the registry keyed by its token.
+ /// The browse session to register.
public void Register(IBrowseSession session) => _sessions[session.Token] = session;
/// Looks up a session by token without removing it.
+ /// The token to look up.
+ /// The session, if found.
+ /// true if the session was found; otherwise false.
public bool TryGet(Guid token, out IBrowseSession session) =>
_sessions.TryGetValue(token, out session!);
/// Atomically removes a session from the registry, returning it for disposal.
+ /// The token of the session to remove.
+ /// The removed session, if found.
+ /// true if the session was removed; otherwise false.
public bool TryRemove(Guid token, out IBrowseSession session) =>
_sessions.TryRemove(token, out session!);
/// Returns a point-in-time snapshot of all currently registered sessions.
+ /// A read-only list of token/session pairs.
public IReadOnlyList<(Guid Token, IBrowseSession Session)> Snapshot() =>
_sessions.Select(kv => (kv.Key, kv.Value)).ToList();
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/IBrowserSessionService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/IBrowserSessionService.cs
index b7b171bd..7fb57ed5 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/IBrowserSessionService.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Browsing/IBrowserSessionService.cs
@@ -21,21 +21,38 @@ public interface IBrowserSessionService
{
/// Opens a session against the named driver type using the given JSON config.
/// Never throws — all errors are surfaced via .
+ /// The driver type name to open a browse session for.
+ /// The driver configuration as a JSON string.
+ /// Cancellation token.
+ /// A task that resolves to the open result, including a token on success.
Task OpenAsync(string driverType, string configJson, CancellationToken ct);
/// Returns the root nodes of an open session. Throws
/// if the token is unknown.
+ /// The session token returned by .
+ /// Cancellation token.
+ /// A task that resolves to the root browse nodes.
Task> RootAsync(Guid token, CancellationToken ct);
/// Returns the direct children of in an open session.
/// Throws if the token is unknown.
+ /// The session token returned by .
+ /// The node identifier to expand.
+ /// Cancellation token.
+ /// A task that resolves to the child browse nodes.
Task> ExpandAsync(Guid token, string nodeId, CancellationToken ct);
/// Returns the attributes of in an open session. Throws
/// if the token is unknown.
+ /// The session token returned by .
+ /// The node identifier to read attributes for.
+ /// Cancellation token.
+ /// A task that resolves to the attribute information for the node.
Task> AttributesAsync(Guid token, string nodeId, CancellationToken ct);
/// Removes the session from the registry and disposes it. No-op for unknown tokens.
+ /// The session token to close.
+ /// A task that represents the asynchronous operation.
Task CloseAsync(Guid token);
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/AdminOperationsClient.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/AdminOperationsClient.cs
index 651ec286..8dbec6c0 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/AdminOperationsClient.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/AdminOperationsClient.cs
@@ -25,10 +25,7 @@ public sealed class AdminOperationsClient : IAdminOperationsClient
_proxy = registry.Get();
}
- /// Starts a deployment via the admin operations actor.
- /// The username of who initiated the deployment.
- /// The cancellation token.
- /// The deployment start result.
+ ///
public async Task StartDeploymentAsync(string createdBy, CancellationToken ct)
{
var msg = new StartDeployment(createdBy, CorrelationId.NewId());
@@ -42,6 +39,10 @@ public sealed class AdminOperationsClient : IAdminOperationsClient
/// Uses the caller-supplied for cancellation; does not impose an
/// additional internal timeout beyond what the proxy itself enforces.
///
+ /// The expected response type from the actor.
+ /// The message to forward to the AdminOperationsActor singleton.
+ /// Cancellation token for the ask operation.
+ /// A task that resolves to the actor's response of type .
public Task AskAsync(object message, CancellationToken ct)
=> _proxy.Ask(message, cancellationToken: ct);
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/AdminProbeService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/AdminProbeService.cs
index 49415b66..4a9d5792 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/AdminProbeService.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/AdminProbeService.cs
@@ -25,6 +25,7 @@ public sealed class AdminProbeService
/// Driver config as JSON (same shape as DriverInstance.DriverConfig).
/// Per-probe timeout; actor clamps to [1, 60].
/// Optional cancellation token from the caller.
+ /// A task that resolves to the from the probe.
public async Task TestAsync(
string driverType,
string configJson,
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/FleetDiagnosticsClient.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/FleetDiagnosticsClient.cs
index 1780d899..81a0b6cc 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/FleetDiagnosticsClient.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/FleetDiagnosticsClient.cs
@@ -31,10 +31,7 @@ public sealed class FleetDiagnosticsClient : IFleetDiagnosticsClient
_systemName = options.Value.SystemName;
}
- /// Gets diagnostics for a cluster node.
- /// The node identifier to query.
- /// Cancellation token.
- /// Diagnostics snapshot for the node, or an empty snapshot if the query fails.
+ ///
public async Task GetDiagnosticsAsync(NodeId nodeId, CancellationToken ct)
{
var selection = _system.ActorSelection($"akka.tcp://{_systemName}@{nodeId.Value}/user/driver-host");
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/ServiceCollectionExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/ServiceCollectionExtensions.cs
index c0d947a2..8aa8debb 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/ServiceCollectionExtensions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Clients/ServiceCollectionExtensions.cs
@@ -10,6 +10,7 @@ public static class ServiceCollectionExtensions
/// Registers the Admin UI client services in the dependency injection container.
///
/// The service collection to register clients into.
+ /// The same service collection for chaining.
public static IServiceCollection AddOtOpcUaAdminClients(this IServiceCollection services)
{
services.AddScoped();
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/AbLegacyAddressBuilder.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/AbLegacyAddressBuilder.cs
index 03137eaf..a9a3d459 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/AbLegacyAddressBuilder.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/AbLegacyAddressBuilder.cs
@@ -7,6 +7,11 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers;
///
public static class AbLegacyAddressBuilder
{
+ /// Builds the canonical AB Legacy PLC address string from its components.
+ /// The file-type prefix (e.g. "N", "F", "B").
+ /// The file number.
+ /// The element index within the file.
+ /// The canonical address string, for example N7:0.
public static string Build(string fileType, int fileNumber, int element)
=> $"{fileType}{fileNumber}:{element}";
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/FocasAddressBuilder.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/FocasAddressBuilder.cs
index b5ebd94c..729c1a77 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/FocasAddressBuilder.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/FocasAddressBuilder.cs
@@ -7,6 +7,10 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers;
///
public static class FocasAddressBuilder
{
+ /// Builds a canonical FOCAS address string from a parameter group and parameter ID.
+ /// The FOCAS parameter group (e.g. "axis").
+ /// The FOCAS parameter identifier.
+ /// The canonical address string in the form group:parameterId.
public static string Build(string group, int parameterId)
=> $"{group}:{parameterId}";
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/HistorianWonderwareAddressBuilder.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/HistorianWonderwareAddressBuilder.cs
index 2fc5b467..df0e19a4 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/HistorianWonderwareAddressBuilder.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/HistorianWonderwareAddressBuilder.cs
@@ -7,6 +7,11 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers;
///
public static class HistorianWonderwareAddressBuilder
{
+ /// Builds a Wonderware Historian address query string from tag name, mode, and interval.
+ /// The Wonderware Historian tag name.
+ /// The retrieval mode (e.g., Cyclic, Delta).
+ /// The retrieval interval in seconds.
+ /// The canonical address query string.
public static string Build(string tagName, string mode, int interval)
=> $"{tagName}?mode={mode}&interval={interval}";
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/ModbusAddressBuilder.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/ModbusAddressBuilder.cs
index 13b90164..3aee2225 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/ModbusAddressBuilder.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/ModbusAddressBuilder.cs
@@ -7,6 +7,11 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers;
///
public static class ModbusAddressBuilder
{
+ /// Builds a canonical Modbus address string from the given register type, offset, and length.
+ /// The register type (Coil, DiscreteInput, Input, or Holding).
+ /// The zero-based register offset.
+ /// The number of registers.
+ /// The canonical address string in the form Xx00000-N.
public static string Build(string regType, int offset, int length)
{
var prefix = regType switch
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/S7AddressBuilder.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/S7AddressBuilder.cs
index 6280681d..7ec13e1b 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/S7AddressBuilder.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/Pickers/S7AddressBuilder.cs
@@ -7,10 +7,12 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers;
///
public static class S7AddressBuilder
{
+ /// Builds the canonical S7 address string from the given components.
/// DB / M / I / Q
/// Only relevant when area == "DB".
/// Byte offset (decimal).
/// X / B / W / D / REAL
+ /// The canonical S7 address string (e.g. DB10.DBD20:REAL, M0.0:X).
public static string Build(string area, int dbNumber, int offset, string s7Type)
{
if (area == "DB")
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/ResilienceFormModel.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/ResilienceFormModel.cs
index 729b6ab3..bc7178da 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/ResilienceFormModel.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Drivers/ResilienceFormModel.cs
@@ -14,19 +14,27 @@ public sealed class ResilienceFormModel
public static readonly string[] Capabilities =
["Read", "Write", "Discover", "Subscribe", "Probe", "AlarmSubscribe", "AlarmAcknowledge", "HistoryRead"];
+ /// Gets or sets the maximum number of concurrent bulkhead operations, or to use the driver default.
public int? BulkheadMaxConcurrent { get; set; }
+ /// Gets or sets the maximum bulkhead queue depth, or to use the driver default.
public int? BulkheadMaxQueue { get; set; }
+ /// Gets or sets the driver recycle interval in seconds, or to use the driver default.
public int? RecycleIntervalSeconds { get; set; }
// capability name -> (timeout, retry, breaker), each nullable.
+ /// Gets or sets the per-capability policy overrides keyed by capability name.
public Dictionary Policies { get; set; } =
Capabilities.ToDictionary(c => c, _ => new CapabilityRow(), StringComparer.OrdinalIgnoreCase);
public sealed class CapabilityRow
{
+ /// Gets or sets the timeout in seconds for this capability, or to use the driver default.
public int? TimeoutSeconds { get; set; }
+ /// Gets or sets the retry count for this capability, or to use the driver default.
public int? RetryCount { get; set; }
+ /// Gets or sets the circuit-breaker failure threshold for this capability, or to use the driver default.
public int? BreakerFailureThreshold { get; set; }
+ /// Gets a value indicating whether all policy fields are null (no overrides set).
public bool IsEmpty => TimeoutSeconds is null && RetryCount is null && BreakerFailureThreshold is null;
}
@@ -37,6 +45,9 @@ public sealed class ResilienceFormModel
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
};
+ /// Deserializes a from the given JSON string, returning an empty model on null or malformed input.
+ /// The JSON string to deserialize, or .
+ /// A populated , or an empty one if is null/blank/malformed.
public static ResilienceFormModel FromJson(string? json)
{
var model = new ResilienceFormModel();
@@ -62,6 +73,7 @@ public sealed class ResilienceFormModel
}
/// Emit only the non-null overrides; returns null when nothing is overridden.
+ /// A JSON string containing only the non-null overrides, or if nothing is overridden.
public string? ToJson()
{
var caps = Policies
@@ -89,16 +101,23 @@ public sealed class ResilienceFormModel
private sealed class Shape
{
+ /// Gets or sets the maximum number of concurrent bulkhead operations.
public int? BulkheadMaxConcurrent { get; set; }
+ /// Gets or sets the maximum bulkhead queue depth.
public int? BulkheadMaxQueue { get; set; }
+ /// Gets or sets the recycle interval in seconds.
public int? RecycleIntervalSeconds { get; set; }
+ /// Gets or sets the per-capability policy shapes.
public Dictionary? CapabilityPolicies { get; set; }
}
private sealed class PolicyShape
{
+ /// Gets or sets the timeout in seconds.
public int? TimeoutSeconds { get; set; }
+ /// Gets or sets the retry count.
public int? RetryCount { get; set; }
+ /// Gets or sets the circuit-breaker failure threshold.
public int? BreakerFailureThreshold { get; set; }
}
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/EndpointRouteBuilderExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/EndpointRouteBuilderExtensions.cs
index eafdbd44..90959eda 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/EndpointRouteBuilderExtensions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/EndpointRouteBuilderExtensions.cs
@@ -18,6 +18,7 @@ public static class EndpointRouteBuilderExtensions
///
/// The root component type for Razor pages.
/// The endpoint route builder.
+ /// The same for chaining.
public static IEndpointRouteBuilder MapAdminUI(this IEndpointRouteBuilder app)
where TApp : IComponent
{
@@ -33,6 +34,7 @@ public static class EndpointRouteBuilderExtensions
/// Adds AdminUI services to the dependency injection container.
///
/// The service collection.
+ /// The same for chaining.
public static IServiceCollection AddAdminUI(this IServiceCollection services)
{
services.AddRazorComponents().AddInteractiveServerComponents();
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/AlertSignalRBridge.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/AlertSignalRBridge.cs
index 906db2a3..145a0683 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/AlertSignalRBridge.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/AlertSignalRBridge.cs
@@ -25,6 +25,7 @@ public sealed class AlertSignalRBridge : ReceiveActor
///
/// The SignalR hub context to send alerts to.
/// In-process fan-out read directly by the Blazor Server Alerts page.
+ /// Akka for creating an actor.
public static Props Props(IHubContext hub, IInProcessBroadcaster broadcaster) =>
Akka.Actor.Props.Create(() => new AlertSignalRBridge(hub, broadcaster));
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/DriverStatusHub.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/DriverStatusHub.cs
index 88a70ee7..0a4de860 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/DriverStatusHub.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/DriverStatusHub.cs
@@ -28,6 +28,8 @@ public sealed class DriverStatusHub : Hub
/// the current snapshot from the in-memory store so the client renders state without
/// waiting for the next change event.
///
+ /// The driver instance identifier to subscribe to.
+ /// A task that represents the asynchronous operation.
public async Task JoinDriver(string driverInstanceId)
{
var groupName = GroupName(driverInstanceId);
@@ -40,5 +42,7 @@ public sealed class DriverStatusHub : Hub
}
/// Builds the SignalR group name for a given driver instance.
+ /// The driver instance identifier.
+ /// The SignalR group name for the specified driver instance.
public static string GroupName(string driverInstanceId) => $"driver:{driverInstanceId}";
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/DriverStatusSignalRBridge.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/DriverStatusSignalRBridge.cs
index 6fc52c9b..88a8215c 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/DriverStatusSignalRBridge.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/DriverStatusSignalRBridge.cs
@@ -24,6 +24,7 @@ public sealed class DriverStatusSignalRBridge : ReceiveActor
/// Creates actor props for a .
/// The SignalR hub context for pushing snapshots to grouped clients.
/// Snapshot store updated before each SignalR push.
+ /// Akka for creating a actor.
public static Props Props(IHubContext hub, IDriverStatusSnapshotStore store) =>
Akka.Actor.Props.Create(() => new DriverStatusSignalRBridge(hub, store));
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/HubRouteBuilderExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/HubRouteBuilderExtensions.cs
index f30b5a55..5e707e48 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/HubRouteBuilderExtensions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/HubRouteBuilderExtensions.cs
@@ -10,6 +10,7 @@ public static class HubRouteBuilderExtensions
/// Maps all OtOpcUa Admin UI SignalR hubs to their configured endpoints.
///
/// The endpoint route builder to register hubs on.
+ /// The same for chaining.
public static IEndpointRouteBuilder MapOtOpcUaHubs(this IEndpointRouteBuilder app)
{
app.MapHub(FleetStatusHub.Endpoint);
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/HubServiceCollectionExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/HubServiceCollectionExtensions.cs
index 3e5a2fff..0e1096e1 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/HubServiceCollectionExtensions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/HubServiceCollectionExtensions.cs
@@ -24,6 +24,7 @@ public static class HubServiceCollectionExtensions
///
///
/// The service collection.
+ /// The same for chaining.
public static IServiceCollection AddOtOpcUaDriverStatusServices(this IServiceCollection services)
{
services.AddSingleton();
@@ -46,6 +47,7 @@ public static class HubServiceCollectionExtensions
///
///
/// The Akka configuration builder.
+ /// The same for chaining.
public static AkkaConfigurationBuilder WithOtOpcUaSignalRBridges(this AkkaConfigurationBuilder builder)
{
builder.WithActors((system, registry, resolver) =>
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/IDriverStatusSnapshotStore.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/IDriverStatusSnapshotStore.cs
index 0527d555..baa49adf 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/IDriverStatusSnapshotStore.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/IDriverStatusSnapshotStore.cs
@@ -11,7 +11,14 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Hubs;
///
public interface IDriverStatusSnapshotStore
{
+ /// Stores or updates the latest health snapshot for the given driver instance.
+ /// The health snapshot to store.
void Upsert(DriverHealthChanged snapshot);
+
+ /// Attempts to retrieve the latest snapshot for the specified driver instance.
+ /// The driver instance identifier to look up.
+ /// The latest snapshot if found; otherwise the default value.
+ /// if a snapshot was found; otherwise .
bool TryGet(string driverInstanceId, out DriverHealthChanged snapshot);
///
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/IInProcessBroadcaster.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/IInProcessBroadcaster.cs
index 46e0d9e8..f4c5f2eb 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/IInProcessBroadcaster.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/IInProcessBroadcaster.cs
@@ -25,6 +25,7 @@ public interface IInProcessBroadcaster
event Action? Received;
/// Fan the item out to all current subscribers.
+ /// The event payload to broadcast to all subscribers.
void Publish(T item);
}
@@ -32,7 +33,7 @@ public interface IInProcessBroadcaster
/// The event payload type.
public sealed class InProcessBroadcaster : IInProcessBroadcaster
{
- ///
+ /// Raised once per with the published item.
public event Action? Received;
///
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/InMemoryDriverStatusSnapshotStore.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/InMemoryDriverStatusSnapshotStore.cs
index 353fe6de..76170b90 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/InMemoryDriverStatusSnapshotStore.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/InMemoryDriverStatusSnapshotStore.cs
@@ -11,7 +11,7 @@ public sealed class InMemoryDriverStatusSnapshotStore : IDriverStatusSnapshotSto
{
private readonly ConcurrentDictionary _byInstance = new();
- ///
+ /// Raised after every with the just-stored snapshot, allowing in-process consumers to receive live updates.
public event Action? SnapshotChanged;
///
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/ScriptLogSignalRBridge.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/ScriptLogSignalRBridge.cs
index 8fac9fb6..9de983f7 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/ScriptLogSignalRBridge.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Hubs/ScriptLogSignalRBridge.cs
@@ -21,6 +21,7 @@ public sealed class ScriptLogSignalRBridge : ReceiveActor
/// Creates a Props instance for the ScriptLogSignalRBridge.
/// The SignalR hub context for sending messages to clients.
/// In-process fan-out read directly by the Blazor Server Script log page.
+ /// An Akka instance for creating a actor.
public static Props Props(IHubContext hub, IInProcessBroadcaster broadcaster) =>
Akka.Actor.Props.Create(() => new ScriptLogSignalRBridge(hub, broadcaster));
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/AdminOperations/ConfigComposer.cs b/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/AdminOperations/ConfigComposer.cs
index b5c637c9..a6cae369 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/AdminOperations/ConfigComposer.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/AdminOperations/ConfigComposer.cs
@@ -25,6 +25,7 @@ public static class ConfigComposer
/// Reads the current configuration and returns a deterministic snapshot blob with revision hash.
/// The configuration database context.
/// The cancellation token for the operation.
+ /// A task resolving to a containing the serialized blob and its SHA-256 hash.
public static async Task SnapshotAndFlattenAsync(
OtOpcUaConfigDbContext db, CancellationToken ct = default)
{
@@ -53,6 +54,7 @@ public static class ConfigComposer
/// Returns the SHA-256 hex digest of the supplied artifact bytes (lowercase, no prefix).
/// The bytes to hash.
+ /// The lowercase hex-encoded SHA-256 digest of the input bytes.
public static string HashOf(ReadOnlySpan blob) =>
Convert.ToHexStringLower(SHA256.HashData(blob));
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/Audit/AuditWriterActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/Audit/AuditWriterActor.cs
index 9f1d3f4a..7474b153 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/Audit/AuditWriterActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/Audit/AuditWriterActor.cs
@@ -39,6 +39,7 @@ public sealed class AuditWriterActor : ReceiveActor, IWithTimers, IAuditWriter
/// Creates a Props factory for the AuditWriterActor.
/// The database context factory for creating ConfigDb connections.
+ /// A Props for creating the .
public static Props Props(IDbContextFactory dbFactory) =>
Akka.Actor.Props.Create(() => new AuditWriterActor(dbFactory));
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/Coordinators/ConfigPublishCoordinator.cs b/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/Coordinators/ConfigPublishCoordinator.cs
index e6cf5ce6..77aa6a01 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/Coordinators/ConfigPublishCoordinator.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.ControlPlane/Coordinators/ConfigPublishCoordinator.cs
@@ -41,6 +41,7 @@ public sealed class ConfigPublishCoordinator : ReceiveActor, IWithTimers
/// Creates actor props for the ConfigPublishCoordinator with the specified configuration.
/// The database context factory for accessing configuration data.
/// The timeout for waiting for apply acknowledgments from cluster nodes.
+ /// Akka to create a actor.
public static Props Props(
IDbContextFactory dbFactory,
TimeSpan? applyDeadline = null) =>
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Host/Drivers/DriverFactoryBootstrap.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Host/Drivers/DriverFactoryBootstrap.cs
index 26ef2284..1671b053 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Host/Drivers/DriverFactoryBootstrap.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Host/Drivers/DriverFactoryBootstrap.cs
@@ -37,6 +37,7 @@ public static class DriverFactoryBootstrap
/// from DI when spawning DriverHostActor.
///
/// The service collection to register driver factories with.
+ /// The instance for chaining.
public static IServiceCollection AddOtOpcUaDriverFactories(this IServiceCollection services)
{
services.AddSingleton(sp =>
@@ -74,6 +75,7 @@ public static class DriverFactoryBootstrap
///
///
/// The service collection to register driver probes with.
+ /// The instance for chaining.
public static IServiceCollection AddOtOpcUaDriverProbes(this IServiceCollection services)
{
services.TryAddEnumerable(ServiceDescriptor.Singleton());
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Host/Health/HealthEndpoints.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Host/Health/HealthEndpoints.cs
index 5e29f6c7..bcef81d7 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Host/Health/HealthEndpoints.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Host/Health/HealthEndpoints.cs
@@ -14,6 +14,8 @@ public static class HealthEndpoints
/// Registers the shared ZB.MOM.WW health probes. Tier semantics preserved: configdb + akka on
/// ready+active; admin-leader on active only.
///
+ /// The service collection to register health checks with.
+ /// The same for chaining.
public static IServiceCollection AddOtOpcUaHealth(this IServiceCollection services)
{
services.AddHealthChecks()
@@ -40,6 +42,7 @@ public static class HealthEndpoints
/// Maps the OtOpcUa health check endpoints to the route builder.
/// The endpoint route builder.
+ /// The same for chaining.
public static IEndpointRouteBuilder MapOtOpcUaHealth(this IEndpointRouteBuilder app)
{
app.MapZbHealth();
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Host/Observability/ObservabilityExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Host/Observability/ObservabilityExtensions.cs
index 34f0d665..da7f3dbd 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Host/Observability/ObservabilityExtensions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Host/Observability/ObservabilityExtensions.cs
@@ -21,6 +21,7 @@ public static class ObservabilityExtensions
/// Otlp; OtOpcUa:Telemetry:OtlpEndpoint sets the OTLP endpoint. With no
/// config the exporter stays Prometheus (the default).
///
+ /// The for chaining.
public static IServiceCollection AddOtOpcUaObservability(this IServiceCollection services, IConfiguration configuration)
{
return services.AddZbTelemetry(o =>
@@ -42,6 +43,7 @@ public static class ObservabilityExtensions
/// the default leaves it unauthenticated for local Prometheus scrapes.
///
/// The endpoint route builder.
+ /// The for chaining.
public static IEndpointRouteBuilder MapOtOpcUaMetrics(this IEndpointRouteBuilder app)
{
app.MapZbMetrics();
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Host/OpcUa/LdapOpcUaUserAuthenticator.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Host/OpcUa/LdapOpcUaUserAuthenticator.cs
index 62858193..47d2a692 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Host/OpcUa/LdapOpcUaUserAuthenticator.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Host/OpcUa/LdapOpcUaUserAuthenticator.cs
@@ -30,6 +30,7 @@ public sealed class LdapOpcUaUserAuthenticator(
/// The username to authenticate.
/// The password to authenticate.
/// Cancellation token.
+ /// A task that resolves to the authentication result (allow or deny with roles).
public async Task AuthenticateUserNameAsync(string username, string password, CancellationToken ct)
{
try
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Host/OpcUa/OtOpcUaServerHostedService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Host/OpcUa/OtOpcUaServerHostedService.cs
index 32506e50..ecc8f8bc 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Host/OpcUa/OtOpcUaServerHostedService.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Host/OpcUa/OtOpcUaServerHostedService.cs
@@ -57,6 +57,7 @@ public sealed class OtOpcUaServerHostedService : IHostedService, IAsyncDisposabl
/// Starts the OPC UA server asynchronously.
///
/// Cancellation token.
+ /// A task that represents the asynchronous start operation.
public async Task StartAsync(CancellationToken cancellationToken)
{
_server = new OtOpcUaSdkServer();
@@ -103,6 +104,7 @@ public sealed class OtOpcUaServerHostedService : IHostedService, IAsyncDisposabl
/// Stops the OPC UA server asynchronously.
///
/// Cancellation token.
+ /// A task that represents the asynchronous stop operation.
public Task StopAsync(CancellationToken cancellationToken)
{
// Revert to Null adapters so any in-flight writes from a poison-pilled actor don't hit a
@@ -115,6 +117,7 @@ public sealed class OtOpcUaServerHostedService : IHostedService, IAsyncDisposabl
///
/// Disposes the hosted service and its resources asynchronously.
///
+ /// A value task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
if (_appHost is not null) await _appHost.DisposeAsync();
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OpcUaApplicationHost.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OpcUaApplicationHost.cs
index 5bd459dd..77b01c31 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OpcUaApplicationHost.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OpcUaApplicationHost.cs
@@ -122,6 +122,7 @@ public sealed class OpcUaApplicationHost : IAsyncDisposable
/// Starts the OPC UA application and server.
/// The standard server instance to start.
/// A cancellation token for the operation.
+ /// A task that represents the asynchronous start operation.
public async Task StartAsync(StandardServer server, CancellationToken cancellationToken)
{
_server = server;
@@ -371,6 +372,7 @@ public sealed class OpcUaApplicationHost : IAsyncDisposable
/// listening endpoints — the misconfiguration is logged and very visible.
///
/// The security profiles to build policies for.
+ /// An enumerable of instances, one per unique profile.
internal static IEnumerable BuildSecurityPolicies(IEnumerable profiles)
{
var seen = new HashSet();
@@ -415,6 +417,7 @@ public sealed class OpcUaApplicationHost : IAsyncDisposable
/// policy works on None endpoints too. F13c will plug a real LDAP-bound validator into
/// StandardServer.SessionManager.ImpersonateUser.
///
+ /// An enumerable of instances for anonymous and username token types.
internal static IEnumerable BuildUserTokenPolicies()
{
yield return new UserTokenPolicy(UserTokenType.Anonymous)
@@ -430,6 +433,7 @@ public sealed class OpcUaApplicationHost : IAsyncDisposable
}
/// Disposes the application host and cleans up resources.
+ /// A that represents the asynchronous dispose operation.
public ValueTask DisposeAsync()
{
if (_impersonateHandler is not null && _server?.CurrentInstance?.SessionManager is { } sessionManager)
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Plan.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Plan.cs
index de2e7c2b..47c19602 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Plan.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/Phase7Plan.cs
@@ -49,6 +49,7 @@ public static class Phase7Planner
///
/// The previous composition result.
/// The new composition result.
+ /// A describing the added, removed, and changed entities.
public static Phase7Plan Compute(Phase7CompositionResult previous, Phase7CompositionResult next)
{
ArgumentNullException.ThrowIfNull(previous);
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/SdkAddressSpaceSink.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/SdkAddressSpaceSink.cs
index 69fb2135..598f248d 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/SdkAddressSpaceSink.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/SdkAddressSpaceSink.cs
@@ -20,37 +20,22 @@ public sealed class SdkAddressSpaceSink : IOpcUaAddressSpaceSink
_nodeManager = nodeManager;
}
- /// Writes a value to the OPC UA address space.
- /// The OPC UA node identifier.
- /// The value being written.
- /// The OPC UA quality status.
- /// The source timestamp in UTC.
+ ///
public void WriteValue(string nodeId, object? value, OpcUaQuality quality, DateTime sourceTimestampUtc)
=> _nodeManager.WriteValue(nodeId, value, quality, sourceTimestampUtc);
- /// Writes alarm state to the OPC UA address space.
- /// The alarm node identifier.
- /// Whether the alarm is active.
- /// Whether the alarm is acknowledged.
- /// The source timestamp in UTC.
+ ///
public void WriteAlarmState(string alarmNodeId, bool active, bool acknowledged, DateTime sourceTimestampUtc)
=> _nodeManager.WriteAlarmState(alarmNodeId, active, acknowledged, sourceTimestampUtc);
- /// Ensures a folder node exists in the address space.
- /// The folder node identifier.
- /// The parent folder node identifier.
- /// The display name for the folder.
+ ///
public void EnsureFolder(string folderNodeId, string? parentNodeId, string displayName)
=> _nodeManager.EnsureFolder(folderNodeId, parentNodeId, displayName);
- /// Ensures a variable node exists in the address space.
- /// The variable node identifier.
- /// The parent folder node identifier.
- /// The display name for the variable.
- /// The OPC UA data type.
+ ///
public void EnsureVariable(string variableNodeId, string? parentFolderNodeId, string displayName, string dataType)
=> _nodeManager.EnsureVariable(variableNodeId, parentFolderNodeId, displayName, dataType);
- /// Rebuilds the entire OPC UA address space.
+ ///
public void RebuildAddressSpace() => _nodeManager.RebuildAddressSpace();
}
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/SdkServiceLevelPublisher.cs b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/SdkServiceLevelPublisher.cs
index b3f34461..e3d8f708 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/SdkServiceLevelPublisher.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/SdkServiceLevelPublisher.cs
@@ -32,8 +32,7 @@ public sealed class SdkServiceLevelPublisher : IServiceLevelPublisher
_logger = logger;
}
- /// Publishes the service level to the OPC UA Server object.
- /// The service level value to publish.
+ ///
public void Publish(byte serviceLevel)
{
var node = _serverInternal.ServerObject?.ServiceLevel;
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DeploymentArtifact.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DeploymentArtifact.cs
index 93368eeb..ae516f65 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DeploymentArtifact.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DeploymentArtifact.cs
@@ -30,6 +30,7 @@ public static class DeploymentArtifact
/// Empty / malformed blobs return an empty list — callers log + treat as "no drivers".
///
/// The deployment artifact blob to parse.
+ /// The parsed list of driver instance specs, or an empty list for empty or malformed input.
public static IReadOnlyList ParseDriverInstances(ReadOnlySpan blob)
{
if (blob.IsEmpty) return Array.Empty();
@@ -92,6 +93,7 @@ public static class DeploymentArtifact
/// nodes.
///
/// The deployment artifact blob to parse.
+ /// The projected composition result, or an empty composition for empty or malformed input.
public static Phase7CompositionResult ParseComposition(ReadOnlySpan blob)
{
if (blob.IsEmpty) return Empty();
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs
index 3e0d2fe9..cd2a475e 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverHostActor.cs
@@ -58,11 +58,13 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
private sealed record ChildEntry(IActorRef Actor, DriverInstanceSpec Spec, bool Stubbed)
{
// Convenience accessors for sites that don't need the full spec.
+ /// Gets the driver type key for this child entry.
public string DriverType => Spec.DriverType;
+ /// Gets the last serialized driver configuration JSON for this child entry.
public string LastConfigJson => Spec.DriverConfig;
}
- ///
+ /// Gets or sets the Akka timer scheduler used by this actor for recurring messages.
public ITimerScheduler Timers { get; set; } = null!;
public sealed class RetryConfigDbConnection
@@ -81,6 +83,7 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
/// Optional actor reference for OPC UA publishing.
/// Optional driver-health publisher; defaults to
/// so test harnesses and smoke fixtures don't need to wire it.
+ /// An Akka instance for creating a .
public static Props Props(
IDbContextFactory dbFactory,
CommonsNodeId localNode,
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverInstanceActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverInstanceActor.cs
index b6f8a296..c525be23 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverInstanceActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverInstanceActor.cs
@@ -100,6 +100,7 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
/// stub paths don't need to provide one.
/// Optional cluster identifier forwarded in messages;
/// defaults to an empty string when not provided (e.g. in unit tests).
+ /// Akka Props for creating a .
public static Props Props(
IDriver driver,
TimeSpan? reconnectInterval = null,
@@ -127,6 +128,7 @@ public sealed class DriverInstanceActor : ReceiveActor, IWithTimers
///
/// The type identifier of the driver.
/// Operational roles configured for this instance.
+ /// true when the driver should start in DEV-STUB mode.
public static bool ShouldStub(string driverType, IEnumerable roles)
{
var isWindowsOnly = driverType is "Galaxy" or "Historian.Wonderware";
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverSpawnPlan.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverSpawnPlan.cs
index 189d2d53..d12c473f 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverSpawnPlan.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Drivers/DriverSpawnPlan.cs
@@ -23,6 +23,7 @@ public static class DriverSpawnPlanner
///
/// The currently running driver children keyed by ID.
/// The target driver instances from the deployment artifact.
+ /// A containing the spawn, delta, and stop sets.
public static DriverSpawnPlan Compute(
IReadOnlyDictionary current,
IReadOnlyList target)
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Health/DbHealthProbeActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Health/DbHealthProbeActor.cs
index 61762d8d..d62eab23 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Health/DbHealthProbeActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/Health/DbHealthProbeActor.cs
@@ -28,6 +28,7 @@ public sealed class DbHealthProbeActor : ReceiveActor, IWithTimers
/// Creates a Props instance for the DbHealthProbeActor.
/// The factory for creating ConfigDb contexts.
+ /// Akka for constructing a .
public static Props Props(IDbContextFactory dbFactory) =>
Akka.Actor.Props.Create(() => new DbHealthProbeActor(dbFactory));
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs
index 6fed3160..b3b23f12 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs
@@ -67,6 +67,7 @@ public sealed class OpcUaPublishActor : ReceiveActor
/// The local cluster node ID.
/// The optional database context factory.
/// The optional Phase 7 applier.
+ /// Akka configured with the OPC UA synchronized dispatcher.
public static Props Props(
IOpcUaAddressSpaceSink? sink = null,
IServiceLevelPublisher? serviceLevel = null,
@@ -89,6 +90,7 @@ public sealed class OpcUaPublishActor : ReceiveActor
/// The local cluster node ID.
/// The optional database context factory.
/// The optional Phase 7 applier.
+ /// Akka suitable for use in a test kit without a pinned dispatcher.
public static Props PropsForTests(
IOpcUaAddressSpaceSink? sink = null,
IServiceLevelPublisher? serviceLevel = null,
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ScriptedAlarms/EfAlarmActorStateStore.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ScriptedAlarms/EfAlarmActorStateStore.cs
index 40d8d34b..1be68720 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ScriptedAlarms/EfAlarmActorStateStore.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ScriptedAlarms/EfAlarmActorStateStore.cs
@@ -30,10 +30,7 @@ public sealed class EfAlarmActorStateStore : IAlarmActorStateStore
_logger = logger;
}
- /// Loads the alarm state snapshot from the database.
- /// The identifier of the alarm.
- /// The cancellation token.
- /// The alarm state snapshot, or null if not found.
+ ///
public async Task LoadAsync(string alarmId, CancellationToken ct)
{
using var db = await _dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false);
@@ -50,9 +47,7 @@ public sealed class EfAlarmActorStateStore : IAlarmActorStateStore
LastAckUser: row.LastAckUser);
}
- /// Saves the alarm state snapshot to the database.
- /// The alarm state snapshot to save.
- /// The cancellation token.
+ ///
public async Task SaveAsync(AlarmActorStateSnapshot snapshot, CancellationToken ct)
{
using var db = await _dbFactory.CreateDbContextAsync(ct).ConfigureAwait(false);
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ServiceCollectionExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ServiceCollectionExtensions.cs
index ae03e824..534a7466 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ServiceCollectionExtensions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/ServiceCollectionExtensions.cs
@@ -36,6 +36,7 @@ public static class ServiceCollectionExtensions
/// Call this BEFORE AddAkka.
///
/// The service collection to register with.
+ /// The same for chaining.
public static IServiceCollection AddOtOpcUaRuntime(this IServiceCollection services)
{
services.TryAddSingleton(NullAlarmHistorianSink.Instance);
@@ -63,6 +64,7 @@ public static class ServiceCollectionExtensions
///
///
/// The Akka configuration builder.
+ /// The same for chaining.
public static AkkaConfigurationBuilder WithOtOpcUaRuntimeActors(this AkkaConfigurationBuilder builder)
{
// Production cluster HOCON (akka.conf) carries this dispatcher block, but consumers that
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/VirtualTags/VirtualTagActor.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/VirtualTags/VirtualTagActor.cs
index d40ebeb7..3aadab37 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/VirtualTags/VirtualTagActor.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Runtime/VirtualTags/VirtualTagActor.cs
@@ -43,6 +43,7 @@ public sealed class VirtualTagActor : ReceiveActor
/// Optional factory for creating DPS publishers.
/// Optional list of dependency tag references; defaults to empty.
/// Optional reference to a dependency multiplexer actor.
+ /// An Akka.NET instance for creating a .
public static Props Props(
string virtualTagId,
string expression,
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Security/Blazor/CookieAuthenticationStateProvider.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Security/Blazor/CookieAuthenticationStateProvider.cs
index cdbd7b39..06116d41 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Security/Blazor/CookieAuthenticationStateProvider.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Security/Blazor/CookieAuthenticationStateProvider.cs
@@ -65,7 +65,8 @@ public sealed class CookieAuthenticationStateProvider : AuthenticationStateProvi
}
}
- ///
+ /// Cancels the authentication ping loop and releases resources.
+ /// A task that represents the asynchronous dispose operation.
public async ValueTask DisposeAsync()
{
_cts.Cancel();
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Security/Jwt/JwtTokenService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Security/Jwt/JwtTokenService.cs
index 89981d9e..342b6996 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Security/Jwt/JwtTokenService.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Security/Jwt/JwtTokenService.cs
@@ -135,6 +135,7 @@ public sealed class JwtTokenService
/// required pairing whenever a JwtBearer scheme is wired.
///
///
+ /// A instance configured with the service's signing key and claim-type aliases.
public TokenValidationParameters BuildValidationParameters() => new()
{
ValidateIssuer = true,
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/LdapOptions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/LdapOptions.cs
index 50afcb4d..d756d647 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/LdapOptions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/LdapOptions.cs
@@ -89,6 +89,7 @@ public sealed class LdapOptions
/// handled by the app wrapper around the library service; is carried
/// through so the library's own feature gate stays consistent with the app master switch.
///
+ /// The projected library LDAP options.
public LibLdapOptions ToLibraryOptions() => new()
{
Enabled = Enabled,
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/OtOpcUaGroupRoleMapper.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/OtOpcUaGroupRoleMapper.cs
index d8500c5e..886f8886 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/OtOpcUaGroupRoleMapper.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/OtOpcUaGroupRoleMapper.cs
@@ -20,7 +20,10 @@ public sealed class OtOpcUaGroupRoleMapper(
IOptions ldapOptions,
ILdapGroupRoleMappingService dbMappings) : IGroupRoleMapper
{
- ///
+ /// Maps LDAP groups to OtOpcUa role claims by combining the appsettings baseline with system-wide DB grants.
+ /// The LDAP groups to map.
+ /// The cancellation token.
+ /// A task that resolves to the merged role mapping with a null scope.
public async Task> MapAsync(IReadOnlyList groups, CancellationToken ct)
{
ArgumentNullException.ThrowIfNull(groups);
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/RoleMapper.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/RoleMapper.cs
index 8e0716e6..c3ed2d32 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/RoleMapper.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Security/Ldap/RoleMapper.cs
@@ -33,6 +33,7 @@ public static class RoleMapper
///
/// Roles already resolved from appsettings (or the dev stub).
/// LdapGroupRoleMapping rows for the user's groups (from GetByGroupsAsync).
+ /// The merged, deduplicated list of role names.
public static IReadOnlyList Merge(
IReadOnlyCollection baselineRoles,
IReadOnlyCollection dbRows)
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs b/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs
index f62b7e5f..cb655ad1 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.Security/ServiceCollectionExtensions.cs
@@ -31,6 +31,7 @@ public static class ServiceCollectionExtensions
///
/// The service collection.
/// The application configuration root.
+ /// The service collection for chaining.
public static IServiceCollection AddOtOpcUaAuth(this IServiceCollection services, IConfiguration configuration)
{
services.AddOptions().Bind(configuration.GetSection(JwtOptions.SectionName));
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/AlarmsCommandTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/AlarmsCommandTests.cs
index 0a671f29..52927834 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/AlarmsCommandTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/AlarmsCommandTests.cs
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class AlarmsCommandTests
{
/// Verifies that Execute subscribes to alarms.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_SubscribesToAlarms()
{
@@ -33,6 +34,7 @@ public class AlarmsCommandTests
}
/// Verifies that Execute with node passes source node ID.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_WithNode_PassesSourceNodeId()
{
@@ -58,6 +60,7 @@ public class AlarmsCommandTests
}
/// Verifies that Execute with refresh requests condition refresh.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_WithRefresh_RequestsConditionRefresh()
{
@@ -83,6 +86,7 @@ public class AlarmsCommandTests
}
/// Verifies that refresh failure prints error.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_RefreshFailure_PrintsError()
{
@@ -110,6 +114,7 @@ public class AlarmsCommandTests
}
/// Verifies that Execute unsubscribes on cancellation.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_UnsubscribesOnCancellation()
{
@@ -132,6 +137,7 @@ public class AlarmsCommandTests
}
/// Verifies that Execute disconnects in finally block.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_DisconnectsInFinally()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/BrowseCommandTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/BrowseCommandTests.cs
index 5cf87e5d..b6e46631 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/BrowseCommandTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/BrowseCommandTests.cs
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class BrowseCommandTests
{
/// Verifies that Execute prints browse results correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_PrintsBrowseResults()
{
@@ -37,6 +38,7 @@ public class BrowseCommandTests
}
/// Verifies that Execute browses from the specified node ID.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_BrowsesFromSpecifiedNode()
{
@@ -60,6 +62,7 @@ public class BrowseCommandTests
}
/// Verifies that Execute browses from null node when not specified.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_DefaultBrowsesFromNull()
{
@@ -81,6 +84,7 @@ public class BrowseCommandTests
}
/// Verifies that Execute browses only a single level when not recursive.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_NonRecursive_BrowsesSingleLevel()
{
@@ -106,6 +110,7 @@ public class BrowseCommandTests
}
/// Verifies that Execute browses child nodes when recursive flag is set.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_Recursive_BrowsesChildren()
{
@@ -129,6 +134,7 @@ public class BrowseCommandTests
}
/// Verifies that Execute disconnects and disposes in the finally block.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_DisconnectsInFinally()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/CommandBaseTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/CommandBaseTests.cs
index d88f7a76..f0ce2d08 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/CommandBaseTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/CommandBaseTests.cs
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class CommandBaseTests
{
/// Verifies that common options map to connection settings correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CommonOptions_MapToConnectionSettings_Correctly()
{
@@ -39,6 +40,7 @@ public class CommandBaseTests
}
/// Verifies that encrypt option maps to SignAndEncrypt.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SecurityOption_Encrypt_MapsToSignAndEncrypt()
{
@@ -57,6 +59,7 @@ public class CommandBaseTests
}
/// Verifies that none option maps to None.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SecurityOption_None_MapsToNone()
{
@@ -75,6 +78,7 @@ public class CommandBaseTests
}
/// Verifies that no failover URLs results in null FailoverUrls.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task NoFailoverUrls_FailoverUrlsIsNull()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/CommandRangeValidationTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/CommandRangeValidationTests.cs
index 67c9bfa6..2afece46 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/CommandRangeValidationTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/CommandRangeValidationTests.cs
@@ -13,6 +13,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class CommandRangeValidationTests
{
/// Verifies that BrowseCommand rejects negative depth values with a command exception.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task BrowseCommand_NegativeDepth_ThrowsCommandException()
{
@@ -30,6 +31,7 @@ public class CommandRangeValidationTests
}
/// Verifies that BrowseCommand rejects zero depth values with a command exception.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task BrowseCommand_ZeroDepth_ThrowsCommandException()
{
@@ -47,6 +49,7 @@ public class CommandRangeValidationTests
}
/// Verifies that SubscribeCommand rejects zero interval values with a command exception.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task SubscribeCommand_ZeroInterval_ThrowsCommandException()
{
@@ -65,6 +68,7 @@ public class CommandRangeValidationTests
}
/// Verifies that SubscribeCommand rejects negative interval values with a command exception.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task SubscribeCommand_NegativeInterval_ThrowsCommandException()
{
@@ -82,6 +86,7 @@ public class CommandRangeValidationTests
}
/// Verifies that SubscribeCommand in recursive mode rejects zero max depth with a command exception.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task SubscribeCommand_RecursiveZeroMaxDepth_ThrowsCommandException()
{
@@ -102,6 +107,7 @@ public class CommandRangeValidationTests
}
/// Verifies that SubscribeCommand rejects negative duration values with a command exception.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task SubscribeCommand_NegativeDuration_ThrowsCommandException()
{
@@ -119,6 +125,7 @@ public class CommandRangeValidationTests
}
/// Verifies that AlarmsCommand rejects zero interval values with a command exception.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task AlarmsCommand_ZeroInterval_ThrowsCommandException()
{
@@ -136,6 +143,7 @@ public class CommandRangeValidationTests
}
/// Verifies that HistoryReadCommand rejects negative max values with a command exception.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task HistoryReadCommand_NegativeMax_ThrowsCommandException()
{
@@ -154,6 +162,7 @@ public class CommandRangeValidationTests
}
/// Verifies that HistoryReadCommand rejects zero interval values with a command exception.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task HistoryReadCommand_ZeroInterval_ThrowsCommandException()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/ConnectCommandTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/ConnectCommandTests.cs
index 7af4170b..37a9f47e 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/ConnectCommandTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/ConnectCommandTests.cs
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class ConnectCommandTests
{
/// Verifies that execute prints connection info.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Execute_PrintsConnectionInfo()
{
@@ -40,6 +41,7 @@ public class ConnectCommandTests
}
/// Verifies that execute calls connect and disconnect.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Execute_CallsConnectAndDisconnect()
{
@@ -59,6 +61,7 @@ public class ConnectCommandTests
}
/// Verifies that execute disconnects on error.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Execute_DisconnectsOnError()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/EventHandlerLifecycleTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/EventHandlerLifecycleTests.cs
index b0200598..ae56e2db 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/EventHandlerLifecycleTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/EventHandlerLifecycleTests.cs
@@ -15,6 +15,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class EventHandlerLifecycleTests
{
/// Verifies that SubscribeCommand detaches the DataChanged event handler after exit.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeCommand_AfterExit_DataChangedEventHasNoSubscribers()
{
@@ -37,6 +38,7 @@ public class EventHandlerLifecycleTests
}
/// Verifies that AlarmsCommand detaches the AlarmEvent handler after exit.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AlarmsCommand_AfterExit_AlarmEventHasNoSubscribers()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/Fakes/FakeOpcUaClientService.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/Fakes/FakeOpcUaClientService.cs
index c10745ad..b10b38e9 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/Fakes/FakeOpcUaClientService.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/Fakes/FakeOpcUaClientService.cs
@@ -126,13 +126,13 @@ public sealed class FakeOpcUaClientService : IOpcUaClientService
///
public ConnectionInfo? CurrentConnectionInfo => ConnectCalled ? ConnectionInfoResult : null;
- ///
+ /// Raised when a subscribed node value changes.
public event EventHandler? DataChanged;
- ///
+ /// Raised when an alarm event is received from the server.
public event EventHandler? AlarmEvent;
- ///
+ /// Raised when the connection state changes.
public event EventHandler? ConnectionStateChanged;
/// True when at least one handler is attached to .
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/Fakes/FakeOpcUaClientServiceFactory.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/Fakes/FakeOpcUaClientServiceFactory.cs
index eca858fe..1063f00d 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/Fakes/FakeOpcUaClientServiceFactory.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/Fakes/FakeOpcUaClientServiceFactory.cs
@@ -17,6 +17,7 @@ public sealed class FakeOpcUaClientServiceFactory : IOpcUaClientServiceFactory
}
/// Creates and returns the fake OPC UA client service.
+ /// The pre-configured instance.
public IOpcUaClientService Create()
{
return _service;
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/HistoryReadCommandTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/HistoryReadCommandTests.cs
index 245bfd07..c5a5388a 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/HistoryReadCommandTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/HistoryReadCommandTests.cs
@@ -10,6 +10,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class HistoryReadCommandTests
{
/// Verifies RawRead execution prints values.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Execute_RawRead_PrintsValues()
{
@@ -44,6 +45,7 @@ public class HistoryReadCommandTests
}
/// Verifies RawRead execution calls HistoryReadRaw.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Execute_RawRead_CallsHistoryReadRaw()
{
@@ -65,6 +67,7 @@ public class HistoryReadCommandTests
}
/// Verifies AggregateRead execution calls HistoryReadAggregate.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Execute_AggregateRead_CallsHistoryReadAggregate()
{
@@ -87,6 +90,7 @@ public class HistoryReadCommandTests
}
/// Verifies AggregateRead execution prints aggregate info.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Execute_AggregateRead_PrintsAggregateInfo()
{
@@ -109,6 +113,7 @@ public class HistoryReadCommandTests
}
/// Verifies invalid aggregate throws CommandException.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Execute_InvalidAggregate_ThrowsCommandException()
{
@@ -129,6 +134,7 @@ public class HistoryReadCommandTests
}
/// Verifies disconnect is called in finally block.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Execute_DisconnectsInFinally()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/InputValidationErrorsTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/InputValidationErrorsTests.cs
index 7a9a7531..b5d972d6 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/InputValidationErrorsTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/InputValidationErrorsTests.cs
@@ -14,6 +14,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class InputValidationErrorsTests
{
/// Verifies that HistoryReadCommand with invalid start time throws CommandException.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HistoryReadCommand_InvalidStartTime_ThrowsCommandException()
{
@@ -32,6 +33,7 @@ public class InputValidationErrorsTests
}
/// Verifies that HistoryReadCommand with invalid end time throws CommandException.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HistoryReadCommand_InvalidEndTime_ThrowsCommandException()
{
@@ -50,6 +52,7 @@ public class InputValidationErrorsTests
}
/// Verifies that HistoryReadCommand with invalid aggregate throws CommandException.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HistoryReadCommand_InvalidAggregate_ThrowsCommandException()
{
@@ -68,6 +71,7 @@ public class InputValidationErrorsTests
}
/// Verifies that ReadCommand with invalid node ID throws CommandException.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadCommand_InvalidNodeId_ThrowsCommandException()
{
@@ -85,6 +89,7 @@ public class InputValidationErrorsTests
}
/// Verifies that SubscribeCommand with invalid node ID throws CommandException.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeCommand_InvalidNodeId_ThrowsCommandException()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/LoggerLifecycleTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/LoggerLifecycleTests.cs
index fe619a68..90e7f306 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/LoggerLifecycleTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/LoggerLifecycleTests.cs
@@ -15,6 +15,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class LoggerLifecycleTests
{
/// Verifies that ConfigureLogging disposes previous logger before reassigning.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ConfigureLogging_DisposesPreviousLogger_BeforeReassigning()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/ReadCommandTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/ReadCommandTests.cs
index 1b894c0a..c2d3831c 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/ReadCommandTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/ReadCommandTests.cs
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class ReadCommandTests
{
/// Verifies that execute prints the read value.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_PrintsReadValue()
{
@@ -41,6 +42,7 @@ public class ReadCommandTests
}
/// Verifies that execute calls read value with correct node ID.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_CallsReadValueWithCorrectNodeId()
{
@@ -60,6 +62,7 @@ public class ReadCommandTests
}
/// Verifies that execute disconnects in finally.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_DisconnectsInFinally()
{
@@ -79,6 +82,7 @@ public class ReadCommandTests
}
/// Verifies that execute disconnects even on read error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_DisconnectsEvenOnReadError()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/RedundancyCommandTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/RedundancyCommandTests.cs
index 755be437..4e5c8afc 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/RedundancyCommandTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/RedundancyCommandTests.cs
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class RedundancyCommandTests
{
/// Verifies that Execute prints redundancy information correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_PrintsRedundancyInfo()
{
@@ -36,6 +37,7 @@ public class RedundancyCommandTests
}
/// Verifies that Execute omits the Server URIs section when none are present.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_NoServerUris_OmitsUriSection()
{
@@ -61,6 +63,7 @@ public class RedundancyCommandTests
}
/// Verifies that Execute calls GetRedundancyInfo on the service.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_CallsGetRedundancyInfo()
{
@@ -78,6 +81,7 @@ public class RedundancyCommandTests
}
/// Verifies that Execute disconnects and disposes in the finally block.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_DisconnectsInFinally()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/SubscribeCommandSummaryTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/SubscribeCommandSummaryTests.cs
index 272d73c1..a7259626 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/SubscribeCommandSummaryTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/SubscribeCommandSummaryTests.cs
@@ -14,6 +14,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class SubscribeCommandSummaryTests
{
/// Verifies that nodes with no updates are counted separately from suspects.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Summary_NodeWithNoUpdate_IsCountedAsNeverNotAsNeverWentBad()
{
@@ -41,6 +42,7 @@ public class SubscribeCommandSummaryTests
}
/// Verifies that nodes with only good values are counted as never went bad.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Summary_NodeReceivedOnlyGoodValues_IsCountedAsNeverWentBad()
{
@@ -73,6 +75,7 @@ public class SubscribeCommandSummaryTests
}
/// Verifies that nodes with bad values are counted as ever went bad.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Summary_NodeReceivedBadValue_IsCountedAsEverWentBad()
{
@@ -102,6 +105,7 @@ public class SubscribeCommandSummaryTests
}
/// Verifies that subscription auto-exits when duration expires.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Duration_ZeroOrPositive_AutoExits()
{
@@ -129,6 +133,7 @@ public class SubscribeCommandSummaryTests
}
/// Verifies that --quiet suppresses updates but prints summary.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Quiet_SuppressesPerUpdateOutputButPrintsSummary()
{
@@ -160,6 +165,7 @@ public class SubscribeCommandSummaryTests
}
/// Verifies that summary is written to disk when summary file is specified.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task SummaryFile_WritesSummaryToDisk()
{
@@ -191,6 +197,7 @@ public class SubscribeCommandSummaryTests
}
/// Verifies that recursive flag browses subtree and subscribes every variable.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Recursive_BrowsesSubtreeAndSubscribesEveryVariable()
{
@@ -230,6 +237,7 @@ public class SubscribeCommandSummaryTests
}
/// Verifies that subscription failures are handled gracefully.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task SubscribeFailure_PrintsFailedMessage_DoesNotCrash()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/SubscribeCommandTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/SubscribeCommandTests.cs
index a9b8c9d6..68c196af 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/SubscribeCommandTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/SubscribeCommandTests.cs
@@ -8,6 +8,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class SubscribeCommandTests
{
/// Verifies that ExecuteAsync subscribes with the correct parameters.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_SubscribesWithCorrectParameters()
{
@@ -37,6 +38,7 @@ public class SubscribeCommandTests
}
/// Verifies that ExecuteAsync unsubscribes when cancellation is requested.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_UnsubscribesOnCancellation()
{
@@ -60,6 +62,7 @@ public class SubscribeCommandTests
}
/// Verifies that ExecuteAsync disconnects and disposes in a finally block.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_DisconnectsInFinally()
{
@@ -84,6 +87,7 @@ public class SubscribeCommandTests
}
/// Verifies that ExecuteAsync prints the correct subscription message.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Execute_PrintsSubscriptionMessage()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/TestConsoleHelper.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/TestConsoleHelper.cs
index f0378a8c..037b89f9 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/TestConsoleHelper.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/TestConsoleHelper.cs
@@ -10,6 +10,7 @@ public static class TestConsoleHelper
///
/// Creates a new for testing.
///
+ /// A new instance.
public static FakeInMemoryConsole CreateConsole()
{
return new FakeInMemoryConsole();
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/WriteCommandTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/WriteCommandTests.cs
index 9e1236d8..15a485a5 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/WriteCommandTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests/WriteCommandTests.cs
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;
public class WriteCommandTests
{
/// Verifies that write command executes successfully.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_WritesSuccessfully()
{
@@ -33,6 +34,7 @@ public class WriteCommandTests
}
/// Verifies that write command reports failure.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_ReportsFailure()
{
@@ -57,6 +59,7 @@ public class WriteCommandTests
}
/// Verifies that write command reads current value before writing.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_ReadsCurrentValueThenWrites()
{
@@ -83,6 +86,7 @@ public class WriteCommandTests
}
/// Verifies that write command disconnects in finally block.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_DisconnectsInFinally()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.Shared.Tests/Fakes/FakeEndpointDiscovery.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.Shared.Tests/Fakes/FakeEndpointDiscovery.cs
index 59cb537d..a5ee3053 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.Shared.Tests/Fakes/FakeEndpointDiscovery.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.Shared.Tests/Fakes/FakeEndpointDiscovery.cs
@@ -12,11 +12,7 @@ internal sealed class FakeEndpointDiscovery : IEndpointDiscovery
/// Gets the last endpoint URL passed to SelectEndpoint.
public string? LastEndpointUrl { get; private set; }
- /// Selects an endpoint for the given configuration and URL, optionally throwing an exception.
- /// The application configuration.
- /// The endpoint URL to select.
- /// The requested security mode.
- /// The selected endpoint description.
+ ///
public EndpointDescription SelectEndpoint(ApplicationConfiguration config, string endpointUrl,
MessageSecurityMode requestedMode)
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.Shared.Tests/OpcUaClientServiceTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.Shared.Tests/OpcUaClientServiceTests.cs
index 0213728b..7cc44f5b 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.Shared.Tests/OpcUaClientServiceTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.Shared.Tests/OpcUaClientServiceTests.cs
@@ -44,6 +44,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that a valid connection request returns populated connection metadata and marks the client as connected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectAsync_ValidSettings_ReturnsConnectionInfo()
{
@@ -58,6 +59,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that invalid connection settings fail validation before any OPC UA session is created.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectAsync_InvalidSettings_ThrowsBeforeCreatingSession()
{
@@ -71,6 +73,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that server and security details from the session are copied into the exposed connection info.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectAsync_PopulatesConnectionInfo()
{
@@ -96,6 +99,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that connection-state transitions are raised for the connecting and connected phases.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectAsync_RaisesConnectionStateChangedEvents()
{
@@ -114,6 +118,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that a failed session creation leaves the client in the disconnected state.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectAsync_SessionFactoryFails_TransitionsToDisconnected()
{
@@ -130,6 +135,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that username and password settings are passed through to the session-creation pipeline.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectAsync_WithUsername_PassesThroughToFactory()
{
@@ -148,6 +154,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that disconnect closes the active session and clears exposed connection state.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DisconnectAsync_WhenConnected_ClosesSession()
{
@@ -164,6 +171,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that disconnect is safe to call when no server session is active.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DisconnectAsync_WhenNotConnected_IsIdempotent()
{
@@ -174,6 +182,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that repeated disconnect calls do not throw after cleanup has already run.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DisconnectAsync_CalledTwice_IsIdempotent()
{
@@ -187,6 +196,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that a connected client can read the current value of a node through the session adapter.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadValueAsync_WhenConnected_ReturnsValue()
{
@@ -206,6 +216,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that reads are rejected when the client is not connected to a server.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadValueAsync_WhenDisconnected_Throws()
{
@@ -216,6 +227,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that session-level read failures are surfaced to callers instead of being swallowed.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadValueAsync_SessionThrows_PropagatesException()
{
@@ -232,6 +244,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that writes succeed through the session adapter when the client is connected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteValueAsync_WhenConnected_WritesValue()
{
@@ -252,6 +265,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that string inputs are coerced to the node's current data type before writing.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteValueAsync_StringValue_CoercesToTargetType()
{
@@ -271,6 +285,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that non-string values are written directly without an extra type-inference read.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteValueAsync_NonStringValue_WritesDirectly()
{
@@ -287,6 +302,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that writes are rejected when the client is disconnected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteValueAsync_WhenDisconnected_Throws()
{
@@ -298,6 +314,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that writing a string to a node whose current read returns a bad status
/// surfaces a clear error instead of writing a mistyped string value (Client.Shared-008).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteValueAsync_StringValueWithBadReadStatus_ThrowsInvalidOperationException()
{
@@ -318,6 +335,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that writing a string to a node whose read returns bad status and null Value
/// surfaces a clear error for both the bad-status case (Client.Shared-008).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteValueAsync_StringValueWithBadStatus_MessageMentionsNode()
{
@@ -339,6 +357,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that browse results are mapped into the client browse model used by CLI and UI consumers.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task BrowseAsync_WhenConnected_ReturnsMappedResults()
{
@@ -368,6 +387,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that a null browse root defaults to the OPC UA Objects folder.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task BrowseAsync_NullParent_UsesObjectsFolder()
{
@@ -386,6 +406,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that object nodes trigger child-detection checks so the client can mark expandable branches.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task BrowseAsync_ObjectNode_ChecksHasChildren()
{
@@ -414,6 +435,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that browse continuation points are followed so multi-page address-space branches are fully returned.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task BrowseAsync_WithContinuationPoint_FollowsIt()
{
@@ -452,6 +474,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that browse requests are rejected when the client is disconnected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task BrowseAsync_WhenDisconnected_Throws()
{
@@ -463,6 +486,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that subscribing to a node creates a monitored item on a data-change subscription.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_CreatesSubscription()
{
@@ -479,6 +503,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that duplicate subscribe requests for the same node do not create duplicate monitored items.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_DuplicateNode_IsIdempotent()
{
@@ -495,6 +520,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that data-change notifications from the subscription are raised through the shared client event.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_RaisesDataChangedEvent()
{
@@ -520,6 +546,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that unsubscribing removes the corresponding monitored item from the active subscription.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnsubscribeAsync_RemovesMonitoredItem()
{
@@ -537,6 +564,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that unsubscribing an unknown node is treated as a safe no-op.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnsubscribeAsync_WhenNotSubscribed_DoesNotThrow()
{
@@ -551,6 +579,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that data subscriptions cannot be created while the client is disconnected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_WhenDisconnected_Throws()
{
@@ -563,6 +592,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that alarm subscription requests create an event monitored item on the session.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAlarmsAsync_CreatesEventSubscription()
{
@@ -579,6 +609,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that duplicate alarm-subscription requests do not create duplicate event subscriptions.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAlarmsAsync_Duplicate_IsIdempotent()
{
@@ -595,6 +626,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that OPC UA event notifications are mapped into the shared client alarm event model.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAlarmsAsync_RaisesAlarmEvent()
{
@@ -643,6 +675,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that removing alarm monitoring deletes the underlying event subscription.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnsubscribeAlarmsAsync_DeletesSubscription()
{
@@ -660,6 +693,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that removing alarms is safe even when no alarm subscription exists.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnsubscribeAlarmsAsync_WhenNoSubscription_DoesNotThrow()
{
@@ -673,6 +707,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that condition refresh requests are forwarded to the active alarm subscription.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RequestConditionRefreshAsync_CallsAdapter()
{
@@ -690,6 +725,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that condition refresh fails fast when no alarm subscription is active.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RequestConditionRefreshAsync_NoAlarmSubscription_Throws()
{
@@ -704,6 +740,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that alarm subscriptions cannot be created while disconnected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAlarmsAsync_WhenDisconnected_Throws()
{
@@ -716,6 +753,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that raw history reads return the session-provided values.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HistoryReadRawAsync_ReturnsValues()
{
@@ -738,6 +776,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that raw history reads are rejected while disconnected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HistoryReadRawAsync_WhenDisconnected_Throws()
{
@@ -748,6 +787,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that raw-history failures from the session are propagated to callers.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HistoryReadRawAsync_SessionThrows_PropagatesException()
{
@@ -762,6 +802,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that aggregate history reads return the processed values from the session adapter.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HistoryReadAggregateAsync_ReturnsValues()
{
@@ -784,6 +825,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that aggregate history reads are rejected while disconnected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HistoryReadAggregateAsync_WhenDisconnected_Throws()
{
@@ -796,6 +838,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that aggregate-history failures from the session are propagated to callers.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task HistoryReadAggregateAsync_SessionThrows_PropagatesException()
{
@@ -814,6 +857,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that redundancy mode, service level, and server URIs are read from the standard OPC UA redundancy nodes.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetRedundancyInfoAsync_ReturnsInfo()
{
@@ -846,6 +890,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that missing optional redundancy arrays do not prevent a redundancy snapshot from being returned.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetRedundancyInfoAsync_MissingOptionalArrays_ReturnsGracefully()
{
@@ -876,6 +921,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that redundancy inspection is rejected while disconnected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetRedundancyInfoAsync_WhenDisconnected_Throws()
{
@@ -887,6 +933,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that RedundancySupport boxed as a different numeric type (e.g. short) is handled
/// without InvalidCastException — defensive Convert.ToInt32 coercion (Client.Shared-002).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetRedundancyInfoAsync_RedundancySupportBoxedAsShort_DoesNotThrow()
{
@@ -915,6 +962,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that a bad-status response for RedundancySupport/ServiceLevel falls back to defaults
/// rather than throwing (Client.Shared-002).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetRedundancyInfoAsync_BadStatusOnRequiredReads_ReturnsDefaults()
{
@@ -944,6 +992,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that an alarm event with fewer than 6 fields (but at least 1) is still raised
/// with available fields — the old hard <6 early return silently dropped it (Client.Shared-001).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OnAlarmEvent_TruncatedFields_StillRaisesEvent()
{
@@ -978,6 +1027,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that a null or empty event field list is silently ignored (defensive guard).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OnAlarmEvent_EmptyFields_DoesNotRaiseEvent()
{
@@ -1003,6 +1053,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Verifies that a successful acknowledge call returns
/// and reaches the session adapter's CallMethodAsync (Client.Shared-009).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarmAsync_OnSuccess_ReturnsGood()
{
@@ -1022,6 +1073,7 @@ public class OpcUaClientServiceTests : IDisposable
/// , so callers using
/// if (StatusCode.IsBad(result)) actually see the failure.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarmAsync_OnServiceResultException_ReturnsBadStatusCode()
{
@@ -1044,6 +1096,7 @@ public class OpcUaClientServiceTests : IDisposable
/// source node, but left alone when the caller already passes the condition node —
/// matches the documented contract.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAlarmAsync_LeavesConditionSuffixAlone()
{
@@ -1066,6 +1119,7 @@ public class OpcUaClientServiceTests : IDisposable
/// InAlarm/Acked from the condition node's Galaxy attributes. Verify
/// the alarm event is delivered with the values from the supplemental reads.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OnAlarmEvent_MissingAckedActiveButHasConditionNode_FallbackReadsAndRaisesEvent()
{
@@ -1139,6 +1193,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that a keep-alive failure moves the client to a configured failover endpoint.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KeepAliveFailure_TriggersFailover()
{
@@ -1170,6 +1225,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that connection metadata is refreshed to reflect the newly active failover endpoint.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KeepAliveFailure_UpdatesConnectionInfo()
{
@@ -1196,6 +1252,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that the client falls back to disconnected when every failover endpoint is unreachable.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KeepAliveFailure_AllEndpointsFail_TransitionsToDisconnected()
{
@@ -1217,6 +1274,7 @@ public class OpcUaClientServiceTests : IDisposable
/// failover loop is still in-flight must be ignored, so only one failover runs and only
/// one replacement session is created.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task KeepAliveFailure_ReentrantWhileFailoverInFlight_RunsFailoverOnce()
{
@@ -1255,6 +1313,7 @@ public class OpcUaClientServiceTests : IDisposable
/// Regression for Client.Shared-005: concurrent subscribe/unsubscribe calls mutating the
/// active-subscription bookkeeping must not corrupt the dictionary or throw.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAndUnsubscribe_ConcurrentCalls_DoNotCorruptState()
{
@@ -1283,6 +1342,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that dispose releases the underlying session and clears exposed connection state.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Dispose_CleansUpResources()
{
@@ -1299,6 +1359,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that dispose is safe to call even when no connection was established.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public void Dispose_WhenNotConnected_DoesNotThrow()
{
@@ -1308,6 +1369,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that public operations reject use after the shared client has been disposed.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OperationsAfterDispose_Throw()
{
@@ -1324,6 +1386,7 @@ public class OpcUaClientServiceTests : IDisposable
///
/// Verifies that the factory creates a usable shared OPC UA client service instance.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public void OpcUaClientServiceFactory_CreatesService()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/AlarmsViewModelTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/AlarmsViewModelTests.cs
index d24a1043..02109fa2 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/AlarmsViewModelTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/AlarmsViewModelTests.cs
@@ -47,6 +47,7 @@ public class AlarmsViewModelTests
}
/// Verifies that SubscribeCommand sets IsSubscribed flag.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeCommand_SetsIsSubscribed()
{
@@ -68,6 +69,7 @@ public class AlarmsViewModelTests
}
/// Verifies that UnsubscribeCommand clears IsSubscribed flag.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnsubscribeCommand_ClearsIsSubscribed()
{
@@ -81,6 +83,7 @@ public class AlarmsViewModelTests
}
/// Verifies that RefreshCommand calls the service.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RefreshCommand_CallsService()
{
@@ -156,6 +159,7 @@ public class AlarmsViewModelTests
/// Regression test for Client.UI-006 — when SubscribeAlarmsAsync throws, the failure must be
/// surfaced to the operator via the view model's StatusMessage rather than silently swallowed.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Subscribe_OnFailure_SurfacesStatusMessage()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/BrowseTreeViewModelTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/BrowseTreeViewModelTests.cs
index 92eb1b6c..a9c33958 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/BrowseTreeViewModelTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/BrowseTreeViewModelTests.cs
@@ -30,6 +30,7 @@ public class BrowseTreeViewModelTests
}
/// Verifies that LoadRootsAsync populates root nodes.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LoadRootsAsync_PopulatesRootNodes()
{
@@ -41,6 +42,7 @@ public class BrowseTreeViewModelTests
}
/// Verifies that LoadRootsAsync browses with null parent.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LoadRootsAsync_BrowsesWithNullParent()
{
@@ -61,6 +63,7 @@ public class BrowseTreeViewModelTests
}
/// Verifies that nodes with children have a placeholder.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LoadRootsAsync_NodeWithChildren_HasPlaceholder()
{
@@ -73,6 +76,7 @@ public class BrowseTreeViewModelTests
}
/// Verifies that nodes without children have no placeholder.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LoadRootsAsync_NodeWithoutChildren_HasNoPlaceholder()
{
@@ -84,6 +88,7 @@ public class BrowseTreeViewModelTests
}
/// Verifies that first tree node expand triggers child browse.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TreeNode_FirstExpand_TriggersChildBrowse()
{
@@ -114,6 +119,7 @@ public class BrowseTreeViewModelTests
}
/// Verifies that second tree node expand does not browse again.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TreeNode_SecondExpand_DoesNotBrowseAgain()
{
@@ -143,6 +149,7 @@ public class BrowseTreeViewModelTests
}
/// Verifies that IsLoading transitions during browse.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TreeNode_IsLoading_TransitionsDuringBrowse()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/Fakes/FakeOpcUaClientService.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/Fakes/FakeOpcUaClientService.cs
index 32b7a1a9..1bca9353 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/Fakes/FakeOpcUaClientService.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/Fakes/FakeOpcUaClientService.cs
@@ -136,13 +136,13 @@ public sealed class FakeOpcUaClientService : IOpcUaClientService
///
public ConnectionInfo? CurrentConnectionInfo { get; set; }
- ///
+ /// Raised when a subscribed node value changes.
public event EventHandler? DataChanged;
- ///
+ /// Raised when an alarm condition event is received from the server.
public event EventHandler? AlarmEvent;
- ///
+ /// Raised when the OPC UA session connection state changes.
public event EventHandler? ConnectionStateChanged;
///
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/Fakes/FakeSettingsService.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/Fakes/FakeSettingsService.cs
index 9790e911..c0274d23 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/Fakes/FakeSettingsService.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/Fakes/FakeSettingsService.cs
@@ -13,15 +13,14 @@ public sealed class FakeSettingsService : ISettingsService
/// Gets the last settings that were saved.
public UserSettings? LastSaved { get; private set; }
- /// Loads and returns the current settings.
+ ///
public UserSettings Load()
{
LoadCallCount++;
return Settings;
}
- /// Saves the specified settings.
- /// The settings to save.
+ ///
public void Save(UserSettings settings)
{
SaveCallCount++;
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/HistoryViewModelTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/HistoryViewModelTests.cs
index e0b65e5e..f10679d3 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/HistoryViewModelTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/HistoryViewModelTests.cs
@@ -60,6 +60,7 @@ public class HistoryViewModelTests
}
/// Verifies that a raw history read populates results correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadHistoryCommand_Raw_PopulatesResults()
{
@@ -77,6 +78,7 @@ public class HistoryViewModelTests
}
/// Verifies that an aggregate history read populates results correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadHistoryCommand_Aggregate_PopulatesResults()
{
@@ -94,6 +96,7 @@ public class HistoryViewModelTests
}
/// Verifies that the read history command clears previous results before loading new ones.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadHistoryCommand_ClearsResultsBefore()
{
@@ -107,6 +110,7 @@ public class HistoryViewModelTests
}
/// Verifies that the loading state is false after the read history command completes.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadHistoryCommand_IsLoading_FalseAfterComplete()
{
@@ -158,6 +162,7 @@ public class HistoryViewModelTests
}
/// Verifies that read history command errors are displayed in the results.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadHistoryCommand_Error_ShowsErrorInResults()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/MainWindowViewModelTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/MainWindowViewModelTests.cs
index dfb02a37..24a5c1a0 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/MainWindowViewModelTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/MainWindowViewModelTests.cs
@@ -76,6 +76,7 @@ public class MainWindowViewModelTests
///
/// Verifies that a successful connect command updates the shell into the connected state.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_TransitionsToConnected()
{
@@ -89,6 +90,7 @@ public class MainWindowViewModelTests
///
/// Verifies that the initial browse tree is loaded after a successful connect.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_LoadsRootNodes()
{
@@ -101,6 +103,7 @@ public class MainWindowViewModelTests
///
/// Verifies that redundancy details are fetched and exposed after connecting.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_FetchesRedundancyInfo()
{
@@ -114,6 +117,7 @@ public class MainWindowViewModelTests
///
/// Verifies that the session label shows the connected server and session identity.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_SetsSessionLabel()
{
@@ -126,6 +130,7 @@ public class MainWindowViewModelTests
///
/// Verifies that disconnect returns the shell to the disconnected state.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DisconnectCommand_TransitionsToDisconnected()
{
@@ -140,6 +145,7 @@ public class MainWindowViewModelTests
///
/// Verifies that disconnect clears session-specific UI state such as browse data and redundancy details.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Disconnect_ClearsStateAndChildren()
{
@@ -155,6 +161,7 @@ public class MainWindowViewModelTests
///
/// Verifies that connection-state events from the client update the shell status text and state.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectionStateChangedEvent_UpdatesState()
{
@@ -171,6 +178,7 @@ public class MainWindowViewModelTests
///
/// Verifies that selecting a tree node updates the dependent read/write and history panels.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SelectedTreeNode_PropagatesToChildViewModels()
{
@@ -186,6 +194,7 @@ public class MainWindowViewModelTests
///
/// Verifies that a successful connect propagates connected state into the child tabs.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_PropagatesIsConnectedToChildViewModels()
{
@@ -200,6 +209,7 @@ public class MainWindowViewModelTests
///
/// Verifies that disconnect propagates disconnected state into the child tabs.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DisconnectCommand_PropagatesIsConnectedFalseToChildViewModels()
{
@@ -215,6 +225,7 @@ public class MainWindowViewModelTests
///
/// Verifies that failed connection attempts restore the disconnected shell state and surface the error text.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectFailure_RevertsToDisconnected()
{
@@ -229,6 +240,7 @@ public class MainWindowViewModelTests
///
/// Verifies that connection-state transitions raise property-changed notifications for UI binding updates.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task PropertyChanged_FiredForConnectionState()
{
@@ -260,6 +272,7 @@ public class MainWindowViewModelTests
///
/// Verifies that failover endpoint text is parsed into connection settings on connect.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_MapsFailoverUrlsToSettings()
{
@@ -276,6 +289,7 @@ public class MainWindowViewModelTests
///
/// Verifies that empty failover text is normalized to no configured failover endpoints.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_MapsEmptyFailoverUrlsToNull()
{
@@ -289,6 +303,7 @@ public class MainWindowViewModelTests
///
/// Verifies that the configured session timeout is passed into the connection settings.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_MapsSessionTimeoutToSettings()
{
@@ -302,6 +317,7 @@ public class MainWindowViewModelTests
///
/// Verifies that the auto-accept certificate toggle is passed into the connection settings.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_MapsAutoAcceptCertificatesToSettings()
{
@@ -315,6 +331,7 @@ public class MainWindowViewModelTests
///
/// Verifies that a custom certificate store path is passed into the connection settings.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_MapsCertificateStorePathToSettings()
{
@@ -328,6 +345,7 @@ public class MainWindowViewModelTests
///
/// Verifies that subscribing selected nodes adds subscriptions and switches the shell to the subscriptions tab.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeSelectedNodesCommand_SubscribesAndSwitchesToTab()
{
@@ -348,6 +366,7 @@ public class MainWindowViewModelTests
///
/// Verifies that subscribing selected nodes is a no-op when nothing is selected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeSelectedNodesCommand_DoesNothing_WhenNoSelection()
{
@@ -361,6 +380,7 @@ public class MainWindowViewModelTests
///
/// Verifies that the history command targets the selected node and switches the shell to the history tab.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ViewHistoryForSelectedNodeCommand_SetsNodeAndSwitchesToTab()
{
@@ -378,6 +398,7 @@ public class MainWindowViewModelTests
///
/// Verifies that history actions are enabled when a variable node is selected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UpdateHistoryEnabledForSelection_TrueForVariableNode()
{
@@ -395,6 +416,7 @@ public class MainWindowViewModelTests
///
/// Verifies that history actions stay disabled when an object node rather than a variable is selected.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UpdateHistoryEnabledForSelection_FalseForObjectNode()
{
@@ -470,6 +492,7 @@ public class MainWindowViewModelTests
///
/// Verifies that successful connections persist the current connection settings.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_SavesSettingsOnSuccess()
{
@@ -487,6 +510,7 @@ public class MainWindowViewModelTests
///
/// Verifies that failed connection attempts do not overwrite saved settings.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_DoesNotSaveOnFailure()
{
@@ -500,6 +524,7 @@ public class MainWindowViewModelTests
///
/// Verifies that active subscriptions are persisted when the shell disconnects.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_SavesSubscribedNodes()
{
@@ -522,6 +547,7 @@ public class MainWindowViewModelTests
/// view model must leave RedundancyInfo null without crashing or hiding the diagnostic.
/// The Status text is expected to remain "Connected" (redundancy is optional).
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_RedundancyFailure_DoesNotBreakConnection()
{
@@ -538,6 +564,7 @@ public class MainWindowViewModelTests
///
/// Verifies that saved subscriptions are restored after reconnecting the shell.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConnectCommand_RestoresSavedSubscriptions()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/ReadWriteViewModelTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/ReadWriteViewModelTests.cs
index 24caa13c..1a276d2d 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/ReadWriteViewModelTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/ReadWriteViewModelTests.cs
@@ -51,6 +51,7 @@ public class ReadWriteViewModelTests
}
/// Verifies that the read command updates value and status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadCommand_UpdatesValueAndStatus()
{
@@ -91,6 +92,7 @@ public class ReadWriteViewModelTests
}
/// Verifies that the write command updates write status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task WriteCommand_UpdatesWriteStatus()
{
@@ -118,6 +120,7 @@ public class ReadWriteViewModelTests
}
/// Verifies that read command error sets error status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadCommand_Error_SetsErrorStatus()
{
diff --git a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/SubscriptionsViewModelTests.cs b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/SubscriptionsViewModelTests.cs
index 8c4fd3f5..4a35d498 100644
--- a/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/SubscriptionsViewModelTests.cs
+++ b/tests/Client/ZB.MOM.WW.OtOpcUa.Client.UI.Tests/SubscriptionsViewModelTests.cs
@@ -41,6 +41,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that AddSubscriptionCommand adds a new subscription to the active list.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task AddSubscriptionCommand_AddsItem()
{
@@ -58,6 +59,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that RemoveSubscriptionCommand removes selected subscription.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task RemoveSubscriptionCommand_RemovesItem()
{
@@ -83,6 +85,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that DataChanged event updates the matching subscription row.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task DataChanged_UpdatesMatchingRow()
{
@@ -98,6 +101,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that DataChanged event does not update non-matching subscription rows.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task DataChanged_DoesNotUpdateNonMatchingRow()
{
@@ -146,6 +150,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that AddSubscriptionForNodeAsync adds a subscription.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task AddSubscriptionForNodeAsync_AddsSubscription()
{
@@ -160,6 +165,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that AddSubscriptionForNodeAsync skips duplicate subscriptions.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task AddSubscriptionForNodeAsync_SkipsDuplicate()
{
@@ -173,6 +179,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that AddSubscriptionForNodeAsync does nothing when disconnected.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task AddSubscriptionForNodeAsync_DoesNothing_WhenDisconnected()
{
@@ -185,6 +192,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that GetSubscribedNodeIds returns all active subscription node IDs.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task GetSubscribedNodeIds_ReturnsActiveNodeIds()
{
@@ -200,6 +208,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that RestoreSubscriptionsAsync subscribes to all provided node IDs.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task RestoreSubscriptionsAsync_SubscribesAllNodes()
{
@@ -212,6 +221,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that ValidateAndWriteAsync returns true on successful write.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ValidateAndWriteAsync_SuccessReturnsTrue()
{
@@ -227,6 +237,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that ValidateAndWriteAsync returns false when value parsing fails.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ValidateAndWriteAsync_ParseFailureReturnsFalse()
{
@@ -242,6 +253,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that ValidateAndWriteAsync returns false when write fails.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ValidateAndWriteAsync_WriteFailureReturnsFalse()
{
@@ -256,6 +268,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that ValidateAndWriteAsync returns false when status is bad.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ValidateAndWriteAsync_BadStatusReturnsFalse()
{
@@ -270,6 +283,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that AddSubscriptionRecursiveAsync subscribes a variable directly.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task AddSubscriptionRecursiveAsync_SubscribesVariableDirectly()
{
@@ -282,6 +296,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that AddSubscriptionRecursiveAsync browses objects and subscribes variable children.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task AddSubscriptionRecursiveAsync_BrowsesObjectAndSubscribesVariableChildren()
{
@@ -302,6 +317,7 @@ public class SubscriptionsViewModelTests
/// Regression test for Client.UI-006 — when SubscribeAsync throws, the failure must be surfaced
/// to the operator via the view model's StatusMessage rather than silently swallowed.
///
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task AddSubscription_OnFailure_SurfacesStatusMessage()
{
@@ -320,6 +336,7 @@ public class SubscriptionsViewModelTests
/// Regression test for Client.UI-006 — silent swallow when adding a subscription for a node
/// (the context-menu helper) must also surface a status to the operator.
///
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task AddSubscriptionForNodeAsync_OnFailure_SurfacesStatusMessage()
{
@@ -334,6 +351,7 @@ public class SubscriptionsViewModelTests
}
/// Verifies that AddSubscriptionRecursiveAsync recurses through nested objects.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task AddSubscriptionRecursiveAsync_RecursesNestedObjects()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ClusterAuditQueryTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ClusterAuditQueryTests.cs
index ee121383..bc87e6d8 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ClusterAuditQueryTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ClusterAuditQueryTests.cs
@@ -51,6 +51,7 @@ public sealed class ClusterAuditQueryTests : IDisposable
/// Structured rows (ClusterId null, NodeId set) for a node in the cluster are now
/// visible, alongside the SP-path rows that stamp ClusterId directly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Surfaces_both_clusterId_rows_and_structured_nodeId_rows()
{
@@ -77,6 +78,7 @@ public sealed class ClusterAuditQueryTests : IDisposable
}
/// An audit row stamped with another cluster's ClusterId never appears.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Does_not_surface_other_cluster_rows()
{
@@ -91,6 +93,7 @@ public sealed class ClusterAuditQueryTests : IDisposable
}
/// Respects the page-size cap, newest first.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Caps_to_page_size_newest_first()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/DriverHostStatusTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/DriverHostStatusTests.cs
index a3f9619a..4f62ee7e 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/DriverHostStatusTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/DriverHostStatusTests.cs
@@ -17,6 +17,7 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Tests;
public sealed class DriverHostStatusTests(SchemaComplianceFixture fixture)
{
/// Verifies that the composite key allows the same host across different nodes or drivers.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Composite_key_allows_same_host_across_different_nodes_or_drivers()
{
@@ -58,6 +59,7 @@ public sealed class DriverHostStatusTests(SchemaComplianceFixture fixture)
}
/// Verifies that the upsert pattern updates existing records in place.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Upsert_pattern_for_same_key_updates_in_place()
{
@@ -97,6 +99,7 @@ public sealed class DriverHostStatusTests(SchemaComplianceFixture fixture)
}
/// Verifies that the State enum is persisted as a string, not an integer.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Enum_persists_as_string_not_int()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/GenerationSealedCacheTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/GenerationSealedCacheTests.cs
index d7ed3121..f5ea53b9 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/GenerationSealedCacheTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/GenerationSealedCacheTests.cs
@@ -33,6 +33,7 @@ public sealed class GenerationSealedCacheTests : IDisposable
};
/// Verifies that reading a snapshot on first boot with no existing snapshot throws.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task FirstBoot_NoSnapshot_ReadThrows()
{
@@ -43,6 +44,7 @@ public sealed class GenerationSealedCacheTests : IDisposable
}
/// Verifies that sealed snapshots can be read back correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SealThenRead_RoundTrips()
{
@@ -58,6 +60,7 @@ public sealed class GenerationSealedCacheTests : IDisposable
}
/// Verifies that sealed files are marked read-only on disk.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SealedFile_IsReadOnly_OnDisk()
{
@@ -71,6 +74,7 @@ public sealed class GenerationSealedCacheTests : IDisposable
}
/// Verifies that the current generation pointer advances when a new generation is sealed.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SealingTwoGenerations_PointerAdvances_ToLatest()
{
@@ -84,6 +88,7 @@ public sealed class GenerationSealedCacheTests : IDisposable
}
/// Verifies that prior generation files are preserved after a new seal.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task PriorGenerationFile_Survives_AfterNewSeal()
{
@@ -97,6 +102,7 @@ public sealed class GenerationSealedCacheTests : IDisposable
}
/// Verifies that reading a corrupt sealed file fails safely.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CorruptSealedFile_ReadFailsClosed()
{
@@ -113,6 +119,7 @@ public sealed class GenerationSealedCacheTests : IDisposable
}
/// Verifies that reading with a missing sealed file fails safely.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task MissingSealedFile_ReadFailsClosed()
{
@@ -129,6 +136,7 @@ public sealed class GenerationSealedCacheTests : IDisposable
}
/// Verifies that reading with a corrupt pointer file fails safely.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CorruptPointerFile_ReadFailsClosed()
{
@@ -143,6 +151,7 @@ public sealed class GenerationSealedCacheTests : IDisposable
}
/// Verifies that sealing the same generation twice is idempotent.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SealSameGenerationTwice_IsIdempotent()
{
@@ -155,6 +164,7 @@ public sealed class GenerationSealedCacheTests : IDisposable
}
/// Verifies that independent clusters do not interfere with each other.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task IndependentClusters_DoNotInterfere()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/LdapGroupRoleMappingServiceTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/LdapGroupRoleMappingServiceTests.cs
index c9ce8e21..afaff2c6 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/LdapGroupRoleMappingServiceTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/LdapGroupRoleMappingServiceTests.cs
@@ -34,6 +34,7 @@ public sealed class LdapGroupRoleMappingServiceTests : IDisposable
};
/// Verifies that Create sets Id and CreatedAtUtc.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Create_SetsId_AndCreatedAtUtc()
{
@@ -47,6 +48,7 @@ public sealed class LdapGroupRoleMappingServiceTests : IDisposable
}
/// Verifies that Create rejects empty LDAP group.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Create_Rejects_EmptyLdapGroup()
{
@@ -58,6 +60,7 @@ public sealed class LdapGroupRoleMappingServiceTests : IDisposable
}
/// Verifies that Create rejects system-wide mapping with ClusterId.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Create_Rejects_SystemWide_With_ClusterId()
{
@@ -69,6 +72,7 @@ public sealed class LdapGroupRoleMappingServiceTests : IDisposable
}
/// Verifies that Create rejects non-system-wide mapping without ClusterId.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Create_Rejects_NonSystemWide_WithoutClusterId()
{
@@ -80,6 +84,7 @@ public sealed class LdapGroupRoleMappingServiceTests : IDisposable
}
/// Verifies that GetByGroups returns only matching grants.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task GetByGroups_Returns_MatchingGrants_Only()
{
@@ -96,6 +101,7 @@ public sealed class LdapGroupRoleMappingServiceTests : IDisposable
}
/// Verifies that GetByGroups returns empty when input is empty.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task GetByGroups_Empty_Input_ReturnsEmpty()
{
@@ -108,6 +114,7 @@ public sealed class LdapGroupRoleMappingServiceTests : IDisposable
}
/// Verifies that ListAll orders results by group then cluster.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ListAll_Orders_ByGroupThenCluster()
{
@@ -125,6 +132,7 @@ public sealed class LdapGroupRoleMappingServiceTests : IDisposable
}
/// Verifies that Delete removes the matching row.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Delete_Removes_Matching_Row()
{
@@ -138,6 +146,7 @@ public sealed class LdapGroupRoleMappingServiceTests : IDisposable
}
/// Verifies that Delete with unknown Id is a no-op.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Delete_Unknown_Id_IsNoOp()
{
@@ -148,6 +157,7 @@ public sealed class LdapGroupRoleMappingServiceTests : IDisposable
}
/// Verifies that a system-wide row (IsSystemWide=true, ClusterId=null) appears in both ListAllAsync and GetByGroupsAsync.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task SystemWide_Row_AppearsIn_ListAll_And_GetByGroups()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/LiteDbConfigCacheTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/LiteDbConfigCacheTests.cs
index 527c5b66..c90bb84f 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/LiteDbConfigCacheTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/LiteDbConfigCacheTests.cs
@@ -24,6 +24,7 @@ public sealed class LiteDbConfigCacheTests : IDisposable
};
/// Verifies that payload is preserved through a write-then-read cycle.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Roundtrip_preserves_payload()
{
@@ -38,6 +39,7 @@ public sealed class LiteDbConfigCacheTests : IDisposable
}
/// Verifies that GetMostRecentAsync returns the latest generation when multiple exist.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task GetMostRecent_returns_latest_when_multiple_generations_present()
{
@@ -50,6 +52,7 @@ public sealed class LiteDbConfigCacheTests : IDisposable
}
/// Verifies that GetMostRecentAsync returns null for an unknown cluster.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task GetMostRecent_returns_null_for_unknown_cluster()
{
@@ -58,6 +61,7 @@ public sealed class LiteDbConfigCacheTests : IDisposable
}
/// Verifies that Prune keeps the latest N generations and drops older ones.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Prune_keeps_latest_N_and_drops_older()
{
@@ -81,6 +85,7 @@ public sealed class LiteDbConfigCacheTests : IDisposable
}
/// Verifies that writing the same cluster/generation twice replaces rather than duplicates.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Put_same_cluster_generation_twice_replaces_not_duplicates()
{
@@ -102,6 +107,7 @@ public sealed class LiteDbConfigCacheTests : IDisposable
// callers could both observe `existing is null` and both Insert.
// ------------------------------------------------------------------------------------
/// Verifies that concurrent PutAsync calls for the same cluster and generation do not create duplicates.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task PutAsync_concurrent_for_same_cluster_and_generation_does_not_duplicate()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ResilientConfigReaderTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ResilientConfigReaderTests.cs
index fd24bdbd..0dad3b99 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ResilientConfigReaderTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests/ResilientConfigReaderTests.cs
@@ -26,6 +26,7 @@ public sealed class ResilientConfigReaderTests : IDisposable
}
/// Verifies that successful central DB reads return value and mark fresh.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task CentralDbSucceeds_ReturnsValue_MarksFresh()
{
@@ -45,6 +46,7 @@ public sealed class ResilientConfigReaderTests : IDisposable
}
/// Verifies that exhausted retries fall back to cache and mark stale.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task CentralDbFails_ExhaustsRetries_FallsBackToCache_MarksStale()
{
@@ -78,6 +80,7 @@ public sealed class ResilientConfigReaderTests : IDisposable
}
/// Verifies that DB failure with unavailable cache throws.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task CentralDbFails_AndCacheAlsoUnavailable_Throws()
{
@@ -99,6 +102,7 @@ public sealed class ResilientConfigReaderTests : IDisposable
}
/// Verifies that cancellation is not retried.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Cancellation_NotRetried()
{
@@ -133,6 +137,7 @@ public sealed class ResilientConfigReaderTests : IDisposable
// ------------------------------------------------------------------------------------
/// Verifies that command timeout TaskCanceledException falls back to cache.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task CommandTimeout_TaskCanceledException_FallsBackToCache()
{
@@ -163,6 +168,7 @@ public sealed class ResilientConfigReaderTests : IDisposable
}
/// Verifies that Polly timeout rejection falls back to cache.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task PollyTimeout_TimeoutRejectedException_FallsBackToCache()
{
@@ -201,6 +207,7 @@ public sealed class ResilientConfigReaderTests : IDisposable
// ------------------------------------------------------------------------------------
/// Verifies that fallback warnings do not log exceptions or password fragments.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task FallbackWarning_does_not_log_full_exception_object_or_password_fragment()
{
@@ -242,6 +249,7 @@ public sealed class ResilientConfigReaderTests : IDisposable
}
/// Verifies that caller cancellation propagates rather than falling back.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task CallerCancellation_Propagates_NotFallback()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/PollGroupEngineTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/PollGroupEngineTests.cs
index 1a0af37f..41ad6eeb 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/PollGroupEngineTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions.Tests/PollGroupEngineTests.cs
@@ -35,6 +35,7 @@ public sealed class PollGroupEngineTests
}
/// Verifies that the initial poll forces an event for every subscribed tag.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Initial_poll_force_raises_every_subscribed_tag()
{
@@ -54,6 +55,7 @@ public sealed class PollGroupEngineTests
}
/// Verifies that unchanged values are only raised once.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Unchanged_value_raises_only_once()
{
@@ -72,6 +74,7 @@ public sealed class PollGroupEngineTests
}
/// Verifies that value changes raise new events.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Value_change_raises_new_event()
{
@@ -92,6 +95,7 @@ public sealed class PollGroupEngineTests
}
/// Verifies that unsubscribe halts the polling loop.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Unsubscribe_halts_the_loop()
{
@@ -113,6 +117,7 @@ public sealed class PollGroupEngineTests
}
/// Verifies that intervals below the configured floor are clamped.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Interval_below_floor_is_clamped()
{
@@ -134,6 +139,7 @@ public sealed class PollGroupEngineTests
}
/// Verifies that multiple subscriptions operate independently.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Multiple_subscriptions_are_independent()
{
@@ -165,6 +171,7 @@ public sealed class PollGroupEngineTests
}
/// Verifies that reader exceptions do not crash the polling loop.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Reader_exception_does_not_crash_loop()
{
@@ -195,6 +202,7 @@ public sealed class PollGroupEngineTests
}
/// Verifies that unsubscribing an unknown handle returns false.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Unsubscribe_unknown_handle_returns_false()
{
@@ -206,6 +214,7 @@ public sealed class PollGroupEngineTests
}
/// Verifies that the active subscription count tracks lifecycle changes.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ActiveSubscriptionCount_tracks_lifecycle()
{
@@ -225,6 +234,7 @@ public sealed class PollGroupEngineTests
}
/// Verifies that disposing the engine cancels all active subscriptions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task DisposeAsync_cancels_all_subscriptions()
{
@@ -253,6 +263,7 @@ public sealed class PollGroupEngineTests
/// must fire only the initial change event, not a spurious event on every tick, even
/// when the driver produces a fresh array instance on each read.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Array_valued_tag_unchanged_contents_raises_only_once()
{
@@ -289,6 +300,7 @@ public sealed class PollGroupEngineTests
/// Core.Abstractions-001: an array-valued tag whose contents change between polls
/// must fire a change event for each distinct set of contents.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Array_valued_tag_changed_contents_raises_event()
{
@@ -320,6 +332,7 @@ public sealed class PollGroupEngineTests
/// violates the documented contract. The engine must throw a descriptive exception
/// rather than silently stalling.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Reader_short_result_list_raises_descriptive_exception_and_loop_continues()
{
@@ -366,6 +379,7 @@ public sealed class PollGroupEngineTests
/// must continue to swallow exceptions (backward compatible). When an error callback IS
/// supplied, every exception caught during a poll cycle must be routed to it.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Reader_exception_is_reported_to_onError_callback()
{
@@ -401,6 +415,7 @@ public sealed class PollGroupEngineTests
/// must also be routed to the error callback so the driver health surface can observe
/// repeated contract violations.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Reader_contract_violation_routes_to_onError_callback()
{
@@ -433,6 +448,7 @@ public sealed class PollGroupEngineTests
/// that itself throws — otherwise a buggy health-surface forwarder would crash the poll
/// loop and silently stall the subscription, defeating the whole point of the callback.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OnError_handler_that_throws_does_not_crash_loop()
{
@@ -463,7 +479,7 @@ public sealed class PollGroupEngineTests
private sealed record DummyHandle : ISubscriptionHandle
{
- /// Gets a diagnostic identifier for this handle.
+ ///
public string DiagnosticId => "dummy";
}
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian.Tests/SqliteStoreAndForwardSinkTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian.Tests/SqliteStoreAndForwardSinkTests.cs
index 0ae583d6..aeb78420 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian.Tests/SqliteStoreAndForwardSinkTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian.Tests/SqliteStoreAndForwardSinkTests.cs
@@ -43,10 +43,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// Gets or sets an exception to throw once.
public Exception? ThrowOnce { get; set; }
- /// Writes a batch of events.
- /// Events to write.
- /// Cancellation token.
- /// A task returning the write outcomes.
+ ///
public Task> WriteBatchAsync(
IReadOnlyList batch, CancellationToken ct)
{
@@ -77,6 +74,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
TimestampUtc: ts ?? DateTime.UtcNow);
/// Verifies that acknowledged events are removed from the queue.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task EnqueueThenDrain_Ack_removes_row()
{
@@ -98,6 +96,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that draining an empty queue is a no-op.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Drain_with_empty_queue_is_noop()
{
@@ -111,6 +110,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that RetryPlease outcome bumps backoff and keeps the row queued.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RetryPlease_bumps_backoff_and_keeps_row()
{
@@ -128,6 +128,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that an Ack after RetryPlease resets backoff to the floor.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Ack_after_Retry_resets_backoff()
{
@@ -147,6 +148,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that PermanentFail outcome dead-letters only the failed event.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task PermanentFail_dead_letters_one_row_only()
{
@@ -165,6 +167,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that writer exceptions trigger retry for the entire batch.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Writer_exception_treated_as_retry_for_whole_batch()
{
@@ -185,6 +188,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that capacity eviction drops the oldest non-dead-lettered row.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Capacity_eviction_drops_oldest_nondeadlettered_row()
{
@@ -209,6 +213,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that dead-lettered rows are purged after retention period expires.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Deadlettered_rows_are_purged_past_retention()
{
@@ -233,6 +238,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that RetryDeadLettered requeues dead-lettered rows for retry.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RetryDeadLettered_requeues_for_retry()
{
@@ -253,6 +259,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that the exponential backoff ladder caps at 60 seconds.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Backoff_ladder_caps_at_60s()
{
@@ -278,6 +285,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that NullAlarmHistorianSink silently swallows enqueue calls.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task NullAlarmHistorianSink_swallows_enqueue()
{
@@ -298,6 +306,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
}
/// Verifies that a disposed sink rejects enqueue operations.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Disposed_sink_rejects_enqueue()
{
@@ -316,6 +325,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// forever), and every good row's outcome is applied to the CORRECT RowId —
/// no good event is silently lost.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Drain_with_corrupt_payload_row_deadletters_it_and_keeps_good_rows_aligned()
{
@@ -347,6 +357,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// A corrupt row at the very head of the queue must be dead-lettered and not
/// prevent the good rows behind it from draining.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Drain_with_corrupt_head_row_does_not_stall_queue()
{
@@ -373,6 +384,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// hammer the writer. We assert that after the backoff ladder advances, the
/// observed inter-batch gap actually grows beyond the bare tick interval.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartDrainLoop_honors_backoff_and_slows_cadence_under_retry()
{
@@ -400,6 +412,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// steady cadence (backoff stays at the floor) — confirms the reschedule path
/// does not get stuck after a successful tick.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartDrainLoop_keeps_steady_cadence_when_writer_is_healthy()
{
@@ -425,6 +438,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// be recorded into the status surface (LastError) and the drain loop must
/// keep rescheduling rather than silently dying.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task StartDrainLoop_records_drain_fault_and_keeps_running()
{
@@ -454,6 +468,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// the busy_timeout + WAL pragmas in place the loser of the file-lock race
/// waits the lock out instead of failing fast.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Concurrent_enqueue_and_drain_do_not_throw_sqlite_busy()
{
@@ -501,10 +516,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// Gets the number of times WriteBatchAsync has been called.
public int CallCount { get; private set; }
- /// Writes a batch of events, throwing once then recovering.
- /// Events to write.
- /// Cancellation token.
- /// A task returning the write outcomes.
+ ///
public Task> WriteBatchAsync(
IReadOnlyList batch, CancellationToken ct)
{
@@ -525,6 +537,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// by the timer callback, but still left the rows stranded on the first
/// cardinality-mismatched tick.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Writer_returning_wrong_cardinality_outcomes_sets_backing_off_and_keeps_rows()
{
@@ -555,6 +568,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// evicted row count must be surfaced in
/// so operators can detect bounded-durability overflow without log scraping.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Capacity_eviction_increments_evicted_count_on_status()
{
@@ -580,6 +594,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// snapshot of all status fields — no torn DateTime? or stale DrainState.
/// Drive status writes from one thread and reads from another concurrently.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetStatus_snapshot_is_consistent_under_concurrent_drain()
{
@@ -632,10 +647,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// Fixes the writer to return correct cardinality.
public void FixWriter() => _returnExtra = false;
- /// Writes a batch of events, returning wrong cardinality until fixed.
- /// Events to write.
- /// Cancellation token.
- /// A task returning the write outcomes.
+ ///
public Task> WriteBatchAsync(
IReadOnlyList batch, CancellationToken ct)
{
@@ -654,6 +666,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// capacity-probe count must stay bounded — not grow proportionally to the
/// enqueue count as the un-optimised path did.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task EnqueueAsync_does_not_count_all_rows_on_every_call_below_capacity()
{
@@ -677,6 +690,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// stay aligned with a fresh COUNT(*) against the database. Catches drift
/// bugs in the in-memory counter introduced by the perf optimisation.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Enqueue_and_drain_keep_queue_depth_consistent_with_storage()
{
@@ -724,6 +738,7 @@ public sealed class SqliteStoreAndForwardSinkTests : IDisposable
/// with storage. Catches drift bugs in the optimised path that would only show
/// up under contention.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Counter_remains_consistent_under_concurrent_enqueue_and_drain()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/FakeUpstream.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/FakeUpstream.cs
index 6ad0a3fc..26ae23d3 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/FakeUpstream.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/FakeUpstream.cs
@@ -38,15 +38,12 @@ public sealed class FakeUpstream : ITagUpstreamSource
}
}
- /// Reads the current value of a tag, or returns a bad-status snapshot if not set.
- /// The tag path to read.
+ ///
public DataValueSnapshot ReadTag(string path)
=> _values.TryGetValue(path, out var v) ? v
: new DataValueSnapshot(null, 0x80340000u, null, DateTime.UtcNow);
- /// Subscribes an observer to tag changes for the given path.
- /// The tag path to subscribe to.
- /// The observer callback to invoke on tag changes.
+ ///
public IDisposable SubscribeTag(string path, Action observer)
{
var list = _subs.GetOrAdd(path, _ => []);
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/ScriptedAlarmEngineTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/ScriptedAlarmEngineTests.cs
index 217e7944..60437333 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/ScriptedAlarmEngineTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/ScriptedAlarmEngineTests.cs
@@ -32,6 +32,7 @@ public sealed class ScriptedAlarmEngineTests
PredicateScriptSource: predicate);
/// Verifies that LoadAsync compiles the alarm predicate and subscribes to all referenced upstream tags.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Load_compiles_and_subscribes_to_referenced_upstreams()
{
@@ -47,6 +48,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that compile failures across multiple alarms are aggregated into a single error.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Compile_failures_aggregated_into_one_error()
{
@@ -63,6 +65,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that an upstream tag change triggers predicate re-evaluation and emits an Activated event.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Upstream_change_re_evaluates_predicate_and_emits_Activated()
{
@@ -84,6 +87,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that clearing an upstream tag value emits a Cleared event and transitions the alarm to Inactive.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Clearing_upstream_emits_Cleared_event()
{
@@ -105,6 +109,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that the message template resolves current tag values at the moment of alarm emission.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Message_template_resolves_tag_values_at_emission()
{
@@ -130,6 +135,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that AcknowledgeAsync records the operator user and persists the ack state to the store.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Ack_records_user_and_persists_to_store()
{
@@ -150,6 +156,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that startup recovery restores the persisted ack state but re-derives the active state from the live predicate.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Startup_recovery_preserves_ack_but_rederives_active_from_predicate()
{
@@ -198,6 +205,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that a shelved alarm transitions its internal state on activation but suppresses the Activated emission.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Shelved_active_transitions_state_but_suppresses_emission()
{
@@ -222,6 +230,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that a runtime exception thrown by a predicate script leaves the alarm state unchanged and does not affect other alarms.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Predicate_runtime_exception_does_not_transition_state()
{
@@ -239,6 +248,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that a disabled alarm does not activate on predicate change and resumes normally after being re-enabled.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Disable_prevents_activation_until_re_enabled()
{
@@ -260,6 +270,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that AddCommentAsync appends to the audit trail without changing the alarm's active or ack state.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AddComment_appends_to_audit_without_state_change()
{
@@ -278,6 +289,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that predicate scripts are forbidden from calling SetVirtualTag, and that the exception is isolated without state change.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Predicate_scripts_cannot_SetVirtualTag()
{
@@ -302,6 +314,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that disposing the engine releases all upstream tag subscriptions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Dispose_releases_upstream_subscriptions()
{
@@ -317,6 +330,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that concurrent reads of alarm state during dictionary mutations do not throw (regression for Core.ScriptedAlarms-001).
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Concurrent_reads_during_mutation_do_not_throw(/* Core.ScriptedAlarms-001 */)
{
@@ -386,6 +400,7 @@ public sealed class ScriptedAlarmEngineTests
// injectable clock — the clock and scriptTimeout constructor parameters
// exist for exactly this.
/// Verifies that a timed shelve automatically expires when the engine's shelving check runs past the unshelve time.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TimedShelve_auto_expires_when_engine_shelving_check_runs(/* -012 (1) */)
{
@@ -423,6 +438,7 @@ public sealed class ScriptedAlarmEngineTests
// (2a) ConfirmAsync end-to-end through the engine.
/// Verifies that ConfirmAsync records the confirming user and emits a Confirmed event persisted to the store.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ConfirmAsync_records_user_and_emits_Confirmed(/* -012 (2) */)
{
@@ -450,6 +466,7 @@ public sealed class ScriptedAlarmEngineTests
// (2b) TimedShelveAsync / UnshelveAsync end-to-end through the engine.
/// Verifies that TimedShelveAsync shelves with a deadline and UnshelveAsync removes the shelve before the timer expires.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task TimedShelveAsync_and_UnshelveAsync_round_trip(/* -012 (2) */)
{
@@ -478,6 +495,7 @@ public sealed class ScriptedAlarmEngineTests
// (2c) EnableAsync end-to-end through the engine.
/// Verifies that EnableAsync transitions the alarm back to Enabled state and emits an Enabled event.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task EnableAsync_re_enables_after_disable(/* -012 (2) */)
{
@@ -501,6 +519,7 @@ public sealed class ScriptedAlarmEngineTests
// the engine or prevent subsequent alarm state transitions. The engine logs
// the exception and continues operating; any later alarm changes still work.
/// Verifies that an exception thrown by an OnEvent subscriber is isolated and does not crash the engine or prevent further state transitions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OnEvent_subscriber_exception_does_not_crash_engine(/* -012 (3) */)
{
@@ -534,6 +553,7 @@ public sealed class ScriptedAlarmEngineTests
// (4) IAlarmStateStore.SaveAsync failure — in-memory state must remain at the
// prior value after finding -007 fix (persist-before-update).
/// Verifies that a store SaveAsync failure leaves the in-memory alarm state at its prior value (persist-before-update invariant, finding -007).
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Store_save_failure_leaves_in_memory_state_unchanged(/* -012 (4) */)
{
@@ -565,6 +585,7 @@ public sealed class ScriptedAlarmEngineTests
// (5) Re-entrant LoadAsync — the old timer must not keep firing after a second
// call (regression for finding -002: _shelvingTimer?.Dispose() fix).
/// Verifies that a second LoadAsync call disposes the prior shelving timer so it does not keep firing after reload (regression for finding -002).
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Second_LoadAsync_does_not_leak_old_timer(/* -012 (5) */)
{
@@ -598,6 +619,7 @@ public sealed class ScriptedAlarmEngineTests
// (6) Cold-start AreInputsReady guard — null value, Bad status, and Uncertain
// status inputs are all handled correctly.
/// Verifies that AreInputsReady blocks predicate evaluation when inputs have null values or Bad status codes, while Uncertain quality is accepted.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AreInputsReady_blocks_evaluation_for_null_and_bad_inputs(/* -012 (6) */)
{
@@ -635,6 +657,7 @@ public sealed class ScriptedAlarmEngineTests
// not deadlock against _evalGate. Both regressions are covered here.
// -------------------------------------------------------------------------
/// Verifies that an OnEvent subscriber can call engine methods (e.g. AcknowledgeAsync) without deadlocking against the evaluation gate (regression for Core.ScriptedAlarms-003).
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task OnEvent_subscriber_can_call_back_into_engine_without_deadlock(/* -003 */)
{
@@ -748,6 +771,7 @@ public sealed class ScriptedAlarmEngineTests
// to a (possibly disposed) store after the engine has returned.
// -------------------------------------------------------------------------
/// Verifies that Dispose blocks until in-flight background re-evaluation tasks complete, preventing the engine from outliving its store (regression for Core.ScriptedAlarms-006).
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Dispose_drains_in_flight_reevaluation_tasks(/* -006 */)
{
@@ -794,6 +818,7 @@ public sealed class ScriptedAlarmEngineTests
// explicitly. The two policies are documented in docs/ScriptedAlarms.md.
// -------------------------------------------------------------------------
/// Verifies that Uncertain-quality inputs are accepted by the predicate but rendered as "{?}" in the operator-facing message template (Core.ScriptedAlarms-010).
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Uncertain_quality_drives_predicate_but_renders_question_mark_in_message(/* -010 */)
{
@@ -842,6 +867,7 @@ public sealed class ScriptedAlarmEngineTests
// consumers).
// -------------------------------------------------------------------------
/// Verifies that the Comments collection is an ImmutableList, enabling O(log n) append and satisfying IReadOnlyList consumers (Core.ScriptedAlarms-008).
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Comments_collection_uses_ImmutableList_for_efficient_append(/* -008 */)
{
@@ -907,29 +933,22 @@ public sealed class ScriptedAlarmEngineTests
/// Gets or sets a value indicating whether the next SaveAsync call should throw a simulated failure.
public bool FailSave { get; set; }
- /// Loads an alarm condition state by ID from the inner store.
- /// The ID of the alarm condition state to load.
- /// A cancellation token.
+ ///
public Task LoadAsync(string alarmId, CancellationToken ct)
=> _inner.LoadAsync(alarmId, ct);
- /// Loads all alarm condition states from the inner store.
- /// A cancellation token.
+ ///
public Task> LoadAllAsync(CancellationToken ct)
=> _inner.LoadAllAsync(ct);
- /// Saves an alarm condition state, optionally throwing if FailSave is set.
- /// The alarm condition state to save.
- /// A cancellation token.
+ ///
public Task SaveAsync(AlarmConditionState state, CancellationToken ct)
{
if (FailSave) throw new InvalidOperationException("Simulated store failure");
return _inner.SaveAsync(state, ct);
}
- /// Removes an alarm condition state by ID from the inner store.
- /// The ID of the alarm condition state to remove.
- /// A cancellation token.
+ ///
public Task RemoveAsync(string alarmId, CancellationToken ct)
=> _inner.RemoveAsync(alarmId, ct);
}
@@ -946,20 +965,15 @@ public sealed class ScriptedAlarmEngineTests
/// Gets a value indicating whether a SaveAsync call is currently blocked waiting on BlockNextSave.
public bool SaveInProgress { get; private set; }
- /// Loads an alarm condition state by ID from the inner store.
- /// The ID of the alarm condition state to load.
- /// A cancellation token.
+ ///
public Task LoadAsync(string alarmId, CancellationToken ct)
=> _inner.LoadAsync(alarmId, ct);
- /// Loads all alarm condition states from the inner store.
- /// A cancellation token.
+ ///
public Task> LoadAllAsync(CancellationToken ct)
=> _inner.LoadAllAsync(ct);
- /// Saves an alarm condition state, optionally blocking on BlockNextSave gate.
- /// The alarm condition state to save.
- /// A cancellation token.
+ ///
public async Task SaveAsync(AlarmConditionState state, CancellationToken ct)
{
var gate = BlockNextSave;
@@ -973,9 +987,7 @@ public sealed class ScriptedAlarmEngineTests
await _inner.SaveAsync(state, ct).ConfigureAwait(false);
}
- /// Removes an alarm condition state by ID from the inner store.
- /// The ID of the alarm condition state to remove.
- /// A cancellation token.
+ ///
public Task RemoveAsync(string alarmId, CancellationToken ct)
=> _inner.RemoveAsync(alarmId, ct);
}
@@ -983,6 +995,7 @@ public sealed class ScriptedAlarmEngineTests
// --- Core.ScriptedAlarms-009: per-alarm evaluation-scratch reuse ---
/// Verifies that re-evaluations reuse the same read cache dictionary instance instead of allocating a new one.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Reevaluation_reuses_the_same_read_cache_dictionary()
{
@@ -1016,6 +1029,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that re-evaluations reuse the same predicate context instance across evaluations.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Reevaluation_reuses_the_same_predicate_context()
{
@@ -1042,6 +1056,7 @@ public sealed class ScriptedAlarmEngineTests
}
/// Verifies that LoadAsync clears prior evaluation scratch so new alarms use fresh scratch.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task LoadAsync_drops_the_prior_generations_scratch()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/ScriptedAlarmSourceTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/ScriptedAlarmSourceTests.cs
index ce499c52..1db4c605 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/ScriptedAlarmSourceTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms.Tests/ScriptedAlarmSourceTests.cs
@@ -41,6 +41,7 @@ public sealed class ScriptedAlarmSourceTests
}
/// Verifies that subscribing with an empty filter receives every alarm emission.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Subscribe_with_empty_filter_receives_every_alarm_emission()
{
@@ -66,6 +67,7 @@ public sealed class ScriptedAlarmSourceTests
}
/// Verifies that subscribing with an equipment prefix filters alarms by that prefix.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Subscribe_with_equipment_prefix_filters_by_that_prefix()
{
@@ -89,6 +91,7 @@ public sealed class ScriptedAlarmSourceTests
}
/// Verifies that unsubscribing stops further alarm events.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Unsubscribe_stops_further_events()
{
@@ -108,6 +111,7 @@ public sealed class ScriptedAlarmSourceTests
}
/// Verifies that AcknowledgeAsync routes to the engine with a default user.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task AcknowledgeAsync_routes_to_engine_with_default_user()
{
@@ -130,6 +134,7 @@ public sealed class ScriptedAlarmSourceTests
}
/// Verifies that null arguments are rejected.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Null_arguments_rejected()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/CompiledScriptCacheTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/CompiledScriptCacheTests.cs
index 3841d6ff..ba67daea 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/CompiledScriptCacheTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/CompiledScriptCacheTests.cs
@@ -66,6 +66,7 @@ public sealed class CompiledScriptCacheTests
}
/// Verifies that a cached evaluator produces correct results when executed.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Cached_evaluator_still_runs_correctly()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/ScriptSandboxTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/ScriptSandboxTests.cs
index 7aecd405..654cd9d9 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/ScriptSandboxTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/ScriptSandboxTests.cs
@@ -27,6 +27,7 @@ public sealed class ScriptSandboxTests
}
/// Verifies that a script can compile, run, and read a seeded tag.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Happy_path_script_runs_and_reads_seeded_tag()
{
@@ -39,6 +40,7 @@ public sealed class ScriptSandboxTests
}
/// Verifies that SetVirtualTag records write operations.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task SetVirtualTag_records_the_write()
{
@@ -316,6 +318,7 @@ public sealed class ScriptSandboxTests
}
/// Verifies that an allowed generic type argument still compiles.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Allowed_generic_type_argument_still_compiles()
{
@@ -331,6 +334,7 @@ public sealed class ScriptSandboxTests
}
/// Verifies that typeof an allowed type still compiles.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Allowed_typeof_still_compiles()
{
@@ -342,6 +346,7 @@ public sealed class ScriptSandboxTests
}
/// Verifies that script exceptions propagate unwrapped.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Script_exception_propagates_unwrapped()
{
@@ -370,6 +375,7 @@ public sealed class ScriptSandboxTests
}
/// Verifies that LINQ Enumerable is available from scripts.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Linq_Enumerable_is_available_from_scripts()
{
@@ -385,6 +391,7 @@ public sealed class ScriptSandboxTests
}
/// Verifies that DataValueSnapshot is usable in scripts.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task DataValueSnapshot_is_usable_in_scripts()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/TimedScriptEvaluatorTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/TimedScriptEvaluatorTests.cs
index f9feeeac..f281fbf6 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/TimedScriptEvaluatorTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests/TimedScriptEvaluatorTests.cs
@@ -14,6 +14,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Scripting.Tests;
public sealed class TimedScriptEvaluatorTests
{
/// Verifies that fast scripts complete under timeout and return value.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Fast_script_completes_under_timeout_and_returns_value()
{
@@ -28,6 +29,7 @@ public sealed class TimedScriptEvaluatorTests
}
/// Verifies that scripts longer than timeout throw ScriptTimeoutException.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Script_longer_than_timeout_throws_ScriptTimeoutException()
{
@@ -50,6 +52,7 @@ public sealed class TimedScriptEvaluatorTests
}
/// Verifies that caller cancellation takes precedence over timeout.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Caller_cancellation_takes_precedence_over_timeout()
{
@@ -108,6 +111,7 @@ public sealed class TimedScriptEvaluatorTests
}
/// Verifies that script exceptions propagate unwrapped.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Script_exception_propagates_unwrapped()
{
@@ -124,6 +128,7 @@ public sealed class TimedScriptEvaluatorTests
}
/// Verifies that ScriptTimeoutException message points at diagnostic path.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ScriptTimeoutException_message_points_at_diagnostic_path()
{
@@ -143,6 +148,7 @@ public sealed class TimedScriptEvaluatorTests
}
/// Verifies that caller cancellation wins even when timeout fires first.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Caller_cancellation_wins_even_when_timeout_fires_first()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/DriverHostTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/DriverHostTests.cs
index 1f6ff319..036aa3ee 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/DriverHostTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/DriverHostTests.cs
@@ -10,10 +10,10 @@ public sealed class DriverHostTests
{
private sealed class StubDriver(string id, bool failInit = false) : IDriver
{
- /// Gets the driver instance identifier.
+ ///
public string DriverInstanceId { get; } = id;
- /// Gets the driver type name.
+ ///
public string DriverType => "Stub";
/// Gets a value indicating whether the driver has been initialized.
@@ -22,9 +22,7 @@ public sealed class DriverHostTests
/// Gets a value indicating whether the driver has been shut down.
public bool ShutDown { get; private set; }
- /// Initializes the driver asynchronously.
- /// Configuration data (unused in stub).
- /// The cancellation token.
+ ///
public Task InitializeAsync(string _, CancellationToken ct)
{
if (failInit) throw new InvalidOperationException("boom");
@@ -32,28 +30,25 @@ public sealed class DriverHostTests
return Task.CompletedTask;
}
- /// Reinitializes the driver asynchronously.
- /// Configuration data (unused in stub).
- /// The cancellation token.
+ ///
public Task ReinitializeAsync(string _, CancellationToken ct) => Task.CompletedTask;
- /// Shuts down the driver asynchronously.
- /// The cancellation token.
+ ///
public Task ShutdownAsync(CancellationToken ct) { ShutDown = true; return Task.CompletedTask; }
- /// Gets the current health status of the driver.
+ ///
public DriverHealth GetHealth() =>
new(Initialized ? DriverState.Healthy : DriverState.Unknown, null, null);
- /// Gets the memory footprint of the driver.
+ ///
public long GetMemoryFootprint() => 0;
- /// Flushes optional caches asynchronously.
- /// The cancellation token.
+ ///
public Task FlushOptionalCachesAsync(CancellationToken ct) => Task.CompletedTask;
}
/// Verifies that registering a driver initializes it and tracks its health.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Register_initializes_driver_and_tracks_health()
{
@@ -68,6 +63,7 @@ public sealed class DriverHostTests
}
/// Verifies that registration rethrows initialization failures but keeps the driver registered.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Register_rethrows_init_failure_but_keeps_driver_registered()
{
@@ -81,6 +77,7 @@ public sealed class DriverHostTests
}
/// Verifies that duplicate driver registration throws an exception.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Duplicate_registration_throws()
{
@@ -92,6 +89,7 @@ public sealed class DriverHostTests
}
/// Verifies that unregistering a driver shuts it down and removes it.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Unregister_shuts_down_and_removes()
{
@@ -113,6 +111,7 @@ public sealed class DriverHostTests
/// The driver awaits an unsettled TaskCompletionSource so it does not introduce its
/// own capture — only DriverHost's await of the returned Task can drive a post.
///
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task RegisterAsync_Does_Not_Capture_SynchronizationContext()
{
@@ -137,6 +136,7 @@ public sealed class DriverHostTests
}
/// Verifies that UnregisterAsync does not capture the synchronization context.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task UnregisterAsync_Does_Not_Capture_SynchronizationContext()
{
@@ -165,6 +165,7 @@ public sealed class DriverHostTests
}
/// Verifies that DisposeAsync does not capture the synchronization context.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task DisposeAsync_Does_Not_Capture_SynchronizationContext()
{
@@ -225,34 +226,28 @@ public sealed class DriverHostTests
/// Driver whose Initialize / Shutdown completions are caller-controlled via TCS.
private sealed class TcsDriver(string id, TaskCompletionSource initTcs, TaskCompletionSource? shutdownTcs = null) : IDriver
{
- /// Gets the driver instance identifier.
+ ///
public string DriverInstanceId { get; } = id;
- /// Gets the driver type name.
+ ///
public string DriverType => "Tcs";
- /// Initializes the driver asynchronously.
- /// Configuration data (unused in TCS driver).
- /// The cancellation token.
+ ///
public Task InitializeAsync(string _, CancellationToken ct) => initTcs.Task;
- /// Reinitializes the driver asynchronously.
- /// Configuration data (unused in TCS driver).
- /// The cancellation token.
+ ///
public Task ReinitializeAsync(string _, CancellationToken ct) => Task.CompletedTask;
- /// Shuts down the driver asynchronously.
- /// The cancellation token.
+ ///
public Task ShutdownAsync(CancellationToken ct) => (shutdownTcs ?? CompletedTcs).Task;
- /// Gets the current health status of the driver.
+ ///
public DriverHealth GetHealth() => new(DriverState.Healthy, null, null);
- /// Gets the memory footprint of the driver.
+ ///
public long GetMemoryFootprint() => 0;
- /// Flushes optional caches asynchronously.
- /// The cancellation token.
+ ///
public Task FlushOptionalCachesAsync(CancellationToken ct) => Task.CompletedTask;
private static readonly TaskCompletionSource CompletedTcs = MakeCompleted();
@@ -271,7 +266,6 @@ public sealed class DriverHostTests
public int PostCount;
public int SendCount;
- /// Posts a callback to the work queue.
///
public override void Post(SendOrPostCallback d, object? state)
{
@@ -279,7 +273,6 @@ public sealed class DriverHostTests
_queue.Enqueue(() => d(state));
}
- /// Sends a callback synchronously.
///
public override void Send(SendOrPostCallback d, object? state)
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/GenericDriverNodeManagerTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/GenericDriverNodeManagerTests.cs
index f2d71510..05d6cce4 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/GenericDriverNodeManagerTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/GenericDriverNodeManagerTests.cs
@@ -15,6 +15,7 @@ public sealed class GenericDriverNodeManagerTests
/// This is the plumbing that PR 16's concrete OPC UA builder will use to update the actual
/// AlarmConditionState nodes.
///
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Alarm_events_are_routed_to_the_sink_registered_for_the_matching_source_node_id()
{
@@ -45,6 +46,7 @@ public sealed class GenericDriverNodeManagerTests
}
/// Verifies that non-alarm variables do not register sinks in the alarm tracker.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Non_alarm_variables_do_not_register_sinks()
{
@@ -59,6 +61,7 @@ public sealed class GenericDriverNodeManagerTests
}
/// Verifies that alarm events with unknown source node IDs are silently dropped.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Unknown_source_node_id_is_dropped_silently()
{
@@ -74,6 +77,7 @@ public sealed class GenericDriverNodeManagerTests
}
/// Verifies that disposing the node manager unsubscribes from alarm events.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Dispose_unsubscribes_from_OnAlarmEvent()
{
@@ -96,6 +100,7 @@ public sealed class GenericDriverNodeManagerTests
/// must unsubscribe the old alarm forwarder and clear the sink registry before re-walking,
/// so alarm transitions are not delivered twice.
///
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Second_BuildAddressSpaceAsync_Does_Not_Double_Fire_Alarms()
{
@@ -121,6 +126,7 @@ public sealed class GenericDriverNodeManagerTests
}
/// Verifies that a second call to BuildAddressSpaceAsync clears the old sink registry.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Second_BuildAddressSpaceAsync_Clears_Old_Sink_Registry()
{
@@ -137,6 +143,7 @@ public sealed class GenericDriverNodeManagerTests
}
/// Verifies that calling BuildAddressSpaceAsync after disposal throws ObjectDisposedException.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task BuildAddressSpaceAsync_After_Dispose_Throws_ObjectDisposedException()
{
@@ -154,6 +161,7 @@ public sealed class GenericDriverNodeManagerTests
/// out of BuildAddressSpaceAsync unhandled so the Server layer's per-driver try/catch
/// (OpcUaApplicationHost.PopulateAddressSpaces) can mark the subtree Faulted.
///
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task BuildAddressSpaceAsync_Propagates_Discovery_Exceptions_To_Caller()
{
@@ -169,33 +177,25 @@ public sealed class GenericDriverNodeManagerTests
/// Driver whose DiscoverAsync throws — exercises the exception-isolation boundary.
private sealed class ThrowingDiscoveryDriver : IDriver, ITagDiscovery
{
- /// Gets the driver instance identifier.
+ ///
public string DriverInstanceId => "throwing";
- /// Gets the driver type name.
+ ///
public string DriverType => "Throwing";
- /// Initializes the driver with configuration.
- /// Configuration JSON (unused in test double).
- /// Cancellation token (unused in test double).
+ ///
public Task InitializeAsync(string _, CancellationToken __) => Task.CompletedTask;
- /// Reinitializes the driver with new configuration.
- /// Configuration JSON (unused in test double).
- /// Cancellation token (unused in test double).
+ ///
public Task ReinitializeAsync(string _, CancellationToken __) => Task.CompletedTask;
- /// Shuts down the driver.
- /// Cancellation token (unused in test double).
+ ///
public Task ShutdownAsync(CancellationToken _) => Task.CompletedTask;
- /// Gets the current health status of the driver.
+ ///
public DriverHealth GetHealth() => new(DriverState.Healthy, null, null);
- /// Gets the memory footprint of the driver.
+ ///
public long GetMemoryFootprint() => 0;
- /// Flushes optional caches in the driver.
- /// Cancellation token (unused in test double).
+ ///
public Task FlushOptionalCachesAsync(CancellationToken _) => Task.CompletedTask;
- /// Discovers the address space by throwing an exception.
- /// The builder used to construct the address space.
- /// Cancellation token.
+ ///
public Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken ct)
=> throw new InvalidOperationException("discovery boom");
}
@@ -204,35 +204,27 @@ public sealed class GenericDriverNodeManagerTests
private sealed class FakeDriver : IDriver, ITagDiscovery, IAlarmSource
{
- /// Gets the driver instance identifier.
+ ///
public string DriverInstanceId => "fake";
- /// Gets the driver type name.
+ ///
public string DriverType => "Fake";
/// Occurs when an alarm event is raised.
public event EventHandler? OnAlarmEvent;
- /// Initializes the driver with configuration.
- /// Configuration JSON.
- /// Cancellation token.
+ ///
public Task InitializeAsync(string driverConfigJson, CancellationToken ct) => Task.CompletedTask;
- /// Reinitializes the driver with new configuration.
- /// Configuration JSON.
- /// Cancellation token.
+ ///
public Task ReinitializeAsync(string driverConfigJson, CancellationToken ct) => Task.CompletedTask;
- /// Shuts down the driver.
- /// Cancellation token.
+ ///
public Task ShutdownAsync(CancellationToken ct) => Task.CompletedTask;
- /// Gets the current health status of the driver.
+ ///
public DriverHealth GetHealth() => new(DriverState.Healthy, DateTime.UtcNow, null);
- /// Gets the memory footprint of the driver.
+ ///
public long GetMemoryFootprint() => 0;
- /// Flushes optional caches in the driver.
- /// Cancellation token.
+ ///
public Task FlushOptionalCachesAsync(CancellationToken ct) => Task.CompletedTask;
- /// Discovers the address space and registers alarm conditions.
- /// The builder used to construct the address space.
- /// Cancellation token.
+ ///
public Task DiscoverAsync(IAddressSpaceBuilder builder, CancellationToken ct)
{
var folder = builder.Folder("Tank", "Tank");
@@ -253,25 +245,19 @@ public sealed class GenericDriverNodeManagerTests
/// The alarm event arguments.
public void RaiseAlarm(AlarmEventArgs args) => OnAlarmEvent?.Invoke(this, args);
- /// Subscribes to alarm events.
- /// Tag references to subscribe to (unused in test double).
- /// Cancellation token (unused in test double).
+ ///
public Task SubscribeAlarmsAsync(IReadOnlyList _, CancellationToken __)
=> Task.FromResult(new FakeHandle("sub"));
- /// Unsubscribes from alarm events.
- /// The subscription handle (unused in test double).
- /// Cancellation token (unused in test double).
+ ///
public Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle _, CancellationToken __) => Task.CompletedTask;
- /// Acknowledges alarm notifications.
- /// Alarm acknowledgement requests (unused in test double).
- /// Cancellation token (unused in test double).
+ ///
public Task AcknowledgeAsync(IReadOnlyList _, CancellationToken __) => Task.CompletedTask;
}
/// Test double for IAlarmSubscriptionHandle.
private sealed class FakeHandle(string diagnosticId) : IAlarmSubscriptionHandle
{
- /// Gets the diagnostic identifier for this subscription.
+ ///
public string DiagnosticId { get; } = diagnosticId;
}
@@ -281,31 +267,22 @@ public sealed class GenericDriverNodeManagerTests
/// Gets the map of alarm sources to their sinks.
public Dictionary Alarms { get; } = new(StringComparer.OrdinalIgnoreCase);
- /// Creates a folder in the address space.
- /// The contained name (unused in test double).
- /// The display name (unused in test double).
+ ///
public IAddressSpaceBuilder Folder(string _, string __) => this;
- /// Creates a variable in the address space.
- /// The contained name (unused in test double).
- /// The display name (unused in test double).
- /// The driver attribute information.
+ ///
public IVariableHandle Variable(string _, string __, DriverAttributeInfo info)
=> new Handle(info.FullName, Alarms);
- /// Adds a property to the current variable.
- /// The property name (unused in test double).
- /// The data type (unused in test double).
- /// The initial value (unused in test double).
+ ///
public void AddProperty(string _, DriverDataType __, object? ___) { }
/// Test double for IVariableHandle.
public sealed class Handle(string fullRef, Dictionary alarms) : IVariableHandle
{
- /// Gets the full reference name for this variable.
+ ///
public string FullReference { get; } = fullRef;
- /// Marks this variable as an alarm condition and registers its sink.
- /// The alarm condition info (unused in test double).
+ ///
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo _)
{
var sink = new RecordingSink();
@@ -319,8 +296,7 @@ public sealed class GenericDriverNodeManagerTests
{
/// Gets the list of alarm transitions received by this sink.
public List Received { get; } = new();
- /// Records an alarm transition.
- /// The alarm event arguments.
+ ///
public void OnTransition(AlarmEventArgs args) => Received.Add(args);
}
}
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Observability/CapabilityInvokerEnrichmentTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Observability/CapabilityInvokerEnrichmentTests.cs
index a6870799..4b74006a 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Observability/CapabilityInvokerEnrichmentTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Observability/CapabilityInvokerEnrichmentTests.cs
@@ -12,6 +12,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Tests.Observability;
public sealed class CapabilityInvokerEnrichmentTests
{
/// Verifies that InvokerExecute logs inside call site with structured properties.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task InvokerExecute_LogsInsideCallSite_CarryStructuredProperties()
{
@@ -45,6 +46,7 @@ public sealed class CapabilityInvokerEnrichmentTests
}
/// Verifies that InvokerExecute does not leak context outside the call site.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task InvokerExecute_DoesNotLeak_ContextOutsideCallSite()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/OpcUa/EquipmentNodeWalkerTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/OpcUa/EquipmentNodeWalkerTests.cs
index 1b22a9d7..0ae74a9e 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/OpcUa/EquipmentNodeWalkerTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/OpcUa/EquipmentNodeWalkerTests.cs
@@ -377,9 +377,7 @@ public sealed class EquipmentNodeWalkerTests
/// Gets the list of properties.
public List Properties { get; } = new();
- /// Creates a folder child node.
- /// The browse name of the folder.
- /// The display name (unused).
+ ///
public IAddressSpaceBuilder Folder(string name, string _)
{
var child = new RecordingBuilder(name);
@@ -387,10 +385,7 @@ public sealed class EquipmentNodeWalkerTests
return child;
}
- /// Creates a variable node.
- /// The browse name of the variable.
- /// The display name (unused).
- /// The attribute information for the variable.
+ ///
public IVariableHandle Variable(string name, string _, DriverAttributeInfo attr)
{
var v = new RecordingVariable(name, attr);
@@ -398,10 +393,7 @@ public sealed class EquipmentNodeWalkerTests
return v;
}
- /// Adds a property to the node.
- /// The browse name of the property.
- /// The data type (unused).
- /// The value of the property.
+ ///
public void AddProperty(string name, DriverDataType _, object? value) =>
Properties.Add(new RecordingProperty(name, value));
}
@@ -412,10 +404,9 @@ public sealed class EquipmentNodeWalkerTests
/// Recorded variable for test verification.
private sealed record RecordingVariable(string BrowseName, DriverAttributeInfo AttributeInfo) : IVariableHandle
{
- /// Gets the full reference of the variable.
+ ///
public string FullReference => AttributeInfo.FullName;
- /// Marks the variable as an alarm condition.
- /// The alarm condition information.
+ ///
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info) => throw new NotSupportedException();
}
}
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/OpcUa/IdentificationFolderBuilderTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/OpcUa/IdentificationFolderBuilderTests.cs
index a997d70d..2c29285b 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/OpcUa/IdentificationFolderBuilderTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/OpcUa/IdentificationFolderBuilderTests.cs
@@ -18,26 +18,18 @@ public sealed class IdentificationFolderBuilderTests
/// Gets or sets the list of added properties.
public List<(string BrowseName, DriverDataType DataType, object? Value)> Properties { get; } = [];
- /// Records a folder and returns this builder for chaining.
- /// The browse name of the folder.
- /// The display name of the folder.
+ ///
public IAddressSpaceBuilder Folder(string browseName, string displayName)
{
Folders.Add((browseName, displayName));
return this; // flat recording — identification fields land in the same bucket
}
- /// Not supported in test context.
- /// The browse name of the variable.
- /// The display name of the variable.
- /// The attribute information.
+ ///
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo attributeInfo)
=> throw new NotSupportedException("Identification fields use AddProperty, not Variable");
- /// Records a property addition.
- /// The browse name of the property.
- /// The data type of the property.
- /// The property value.
+ ///
public void AddProperty(string browseName, DriverDataType dataType, object? value)
=> Properties.Add((browseName, dataType, value));
}
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/AlarmSurfaceInvokerTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/AlarmSurfaceInvokerTests.cs
index 9a883afb..41ff5998 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/AlarmSurfaceInvokerTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/AlarmSurfaceInvokerTests.cs
@@ -11,6 +11,7 @@ public sealed class AlarmSurfaceInvokerTests
private static readonly DriverResilienceOptions TierAOptions = new() { Tier = DriverTier.A };
/// Verifies SubscribeAsync on an empty list returns empty without calling the driver.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_EmptyList_ReturnsEmpty_WithoutDriverCall()
{
@@ -24,6 +25,7 @@ public sealed class AlarmSurfaceInvokerTests
}
/// Verifies SubscribeAsync with no resolver routes through the default host.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_SingleHost_RoutesThroughDefaultHost()
{
@@ -38,6 +40,7 @@ public sealed class AlarmSurfaceInvokerTests
}
/// Verifies SubscribeAsync fans out correctly to multiple hosts based on resolver.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_MultiHost_FansOutByResolvedHost()
{
@@ -57,6 +60,7 @@ public sealed class AlarmSurfaceInvokerTests
}
/// Verifies AcknowledgeAsync does not retry on failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AcknowledgeAsync_DoesNotRetry_OnFailure()
{
@@ -70,6 +74,7 @@ public sealed class AlarmSurfaceInvokerTests
}
/// Verifies SubscribeAsync retries on transient failures.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_Retries_Transient_Failures()
{
@@ -87,6 +92,7 @@ public sealed class AlarmSurfaceInvokerTests
/// Verify by using a per-call resolver with two distinct hosts and checking which host
/// name reaches the driver's UnsubscribeAlarmsAsync.
///
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnsubscribeAsync_Routes_Through_Same_Host_As_Subscribe()
{
@@ -112,6 +118,7 @@ public sealed class AlarmSurfaceInvokerTests
}
/// Verifies UnsubscribeAsync with no resolver uses the default host.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnsubscribeAsync_SingleHost_UsesDefaultHost()
{
@@ -158,10 +165,7 @@ public sealed class AlarmSurfaceInvokerTests
/// Gets the source node IDs from the most recent SubscribeAlarmsAsync call.
public IReadOnlyList LastSubscribedIds { get; private set; } = [];
- /// Subscribes to alarms.
- /// The source node IDs to subscribe to.
- /// Cancellation token.
- /// An alarm subscription handle.
+ ///
public Task SubscribeAlarmsAsync(
IReadOnlyList sourceNodeIds, CancellationToken cancellationToken)
{
@@ -172,20 +176,14 @@ public sealed class AlarmSurfaceInvokerTests
return Task.FromResult(new StubHandle($"h-{SubscribeCallCount}"));
}
- /// Unsubscribes from alarms.
- /// The subscription handle to unsubscribe.
- /// Cancellation token.
- /// A completed task.
+ ///
public Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken)
{
UnsubscribeCallCount++;
return Task.CompletedTask;
}
- /// Acknowledges alarms.
- /// The alarm acknowledgements to process.
- /// Cancellation token.
- /// A completed task.
+ ///
public Task AcknowledgeAsync(
IReadOnlyList acknowledgements, CancellationToken cancellationToken)
{
@@ -194,7 +192,7 @@ public sealed class AlarmSurfaceInvokerTests
return Task.CompletedTask;
}
- /// Occurs when an alarm event is raised.
+ ///
public event EventHandler? OnAlarmEvent { add { } remove { } }
}
@@ -206,9 +204,7 @@ public sealed class AlarmSurfaceInvokerTests
/// The map of source node IDs to host names.
private sealed class StubResolver(Dictionary map) : IPerCallHostResolver
{
- /// Resolves the host for the given full reference.
- /// The full reference to resolve.
- /// The resolved host name.
+ ///
public string ResolveHost(string fullReference) => map[fullReference];
}
}
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/CapabilityInvokerTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/CapabilityInvokerTests.cs
index 277a2307..3b5a9bb3 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/CapabilityInvokerTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/CapabilityInvokerTests.cs
@@ -14,6 +14,7 @@ public sealed class CapabilityInvokerTests
new(builder, "drv-test", () => options);
/// Verifies that the capability invoker returns the value from the call site.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Read_ReturnsValue_FromCallSite()
{
@@ -29,6 +30,7 @@ public sealed class CapabilityInvokerTests
}
/// Verifies that the capability invoker retries on transient failures.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Read_Retries_OnTransientFailure()
{
@@ -52,6 +54,7 @@ public sealed class CapabilityInvokerTests
}
/// Verifies that non-idempotent writes do not retry even when the policy has retries configured.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Write_NonIdempotent_DoesNotRetry_EvenWhenPolicyHasRetries()
{
@@ -85,6 +88,7 @@ public sealed class CapabilityInvokerTests
}
/// Verifies that idempotent writes retry when the policy has retries configured.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Write_Idempotent_Retries_WhenPolicyHasRetries()
{
@@ -116,6 +120,7 @@ public sealed class CapabilityInvokerTests
}
/// Verifies that writes do not retry when the policy has zero retries configured.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Write_Default_DoesNotRetry_WhenPolicyHasZeroRetries()
{
@@ -143,6 +148,7 @@ public sealed class CapabilityInvokerTests
}
/// Verifies that different hosts are honored independently in the resilience pipeline.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Execute_HonorsDifferentHosts_Independently()
{
@@ -161,6 +167,7 @@ public sealed class CapabilityInvokerTests
/// redundant options objects on the per-write hot path and creates a consistency hazard
/// where an Admin edit mid-call could observe two different snapshots.
///
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ExecuteWriteAsync_NonIdempotent_Snapshots_Options_Once_Per_Call()
{
@@ -195,6 +202,7 @@ public sealed class CapabilityInvokerTests
/// two derived values (with base + Resolve(Write)) come from the same options
/// instance.
///
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ExecuteWriteAsync_NonIdempotent_Uses_Consistent_Options_Snapshot()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/DriverResiliencePipelineBuilderTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/DriverResiliencePipelineBuilderTests.cs
index 2a78f3b8..4d64d5e6 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/DriverResiliencePipelineBuilderTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/DriverResiliencePipelineBuilderTests.cs
@@ -13,6 +13,7 @@ public sealed class DriverResiliencePipelineBuilderTests
private static readonly DriverResilienceOptions TierAOptions = new() { Tier = DriverTier.A };
/// Verifies that read operations retry transient failures.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Read_Retries_Transient_Failures()
{
@@ -31,6 +32,7 @@ public sealed class DriverResiliencePipelineBuilderTests
}
/// Verifies that write operations do not retry on failure.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Write_DoesNotRetry_OnFailure()
{
@@ -53,6 +55,7 @@ public sealed class DriverResiliencePipelineBuilderTests
}
/// Verifies that alarm acknowledge operations do not retry on failure.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task AlarmAcknowledge_DoesNotRetry_OnFailure()
{
@@ -115,6 +118,7 @@ public sealed class DriverResiliencePipelineBuilderTests
}
/// Verifies that a dead host does not open the breaker for a sibling host.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task DeadHost_DoesNotOpenBreaker_ForSiblingHost()
{
@@ -146,6 +150,7 @@ public sealed class DriverResiliencePipelineBuilderTests
}
/// Verifies that the circuit breaker opens after the failure threshold on tier A.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task CircuitBreaker_Opens_AfterFailureThreshold_OnTierA()
{
@@ -171,6 +176,7 @@ public sealed class DriverResiliencePipelineBuilderTests
}
/// Verifies that timeout cancels slow operations.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Timeout_Cancels_SlowOperation()
{
@@ -211,6 +217,7 @@ public sealed class DriverResiliencePipelineBuilderTests
}
/// Verifies that cancellation is not retried.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Cancellation_IsNot_Retried()
{
@@ -232,6 +239,7 @@ public sealed class DriverResiliencePipelineBuilderTests
}
/// Verifies that the tracker records failure on every retry.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Tracker_RecordsFailure_OnEveryRetry()
{
@@ -253,6 +261,7 @@ public sealed class DriverResiliencePipelineBuilderTests
}
/// Verifies that the tracker stamps the breaker open when it trips.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Tracker_StampsBreakerOpen_WhenBreakerTrips()
{
@@ -277,6 +286,7 @@ public sealed class DriverResiliencePipelineBuilderTests
}
/// Verifies that the tracker isolates counters per host.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Tracker_IsolatesCounters_PerHost()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/FlakeyDriverIntegrationTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/FlakeyDriverIntegrationTests.cs
index 03433d32..db817511 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/FlakeyDriverIntegrationTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/FlakeyDriverIntegrationTests.cs
@@ -15,6 +15,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Tests.Resilience;
public sealed class FlakeyDriverIntegrationTests
{
/// Verifies read succeeds after transient failures with retries.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Read_SurfacesSuccess_AfterTransientFailures()
{
@@ -43,6 +44,7 @@ public sealed class FlakeyDriverIntegrationTests
}
/// Verifies non-idempotent write fails on first failure without replay.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Write_NonIdempotent_FailsOnFirstFailure_NoReplay()
{
@@ -68,6 +70,7 @@ public sealed class FlakeyDriverIntegrationTests
}
/// Verifies idempotent write retries until success.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Write_Idempotent_RetriesUntilSuccess()
{
@@ -93,6 +96,7 @@ public sealed class FlakeyDriverIntegrationTests
}
/// Verifies multiple hosts have independent failure counts and circuit breakers.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task MultipleHosts_OnOneDriver_HaveIndependentFailureCounts()
{
@@ -141,10 +145,7 @@ public sealed class FlakeyDriverIntegrationTests
_failWritesBeforeIndex = failWritesBeforeIndex;
}
- /// Reads values, failing transiently until the threshold.
- /// Full references to read.
- /// Cancellation token.
- /// Data value snapshots.
+ ///
public Task> ReadAsync(
IReadOnlyList fullReferences,
CancellationToken cancellationToken)
@@ -160,10 +161,7 @@ public sealed class FlakeyDriverIntegrationTests
return Task.FromResult(result);
}
- /// Writes values, failing transiently until the threshold.
- /// The write requests.
- /// Cancellation token.
- /// Write results.
+ ///
public Task> WriteAsync(
IReadOnlyList writes,
CancellationToken cancellationToken)
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/InFlightCounterTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/InFlightCounterTests.cs
index 20c288e4..295d5534 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/InFlightCounterTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/InFlightCounterTests.cs
@@ -69,6 +69,7 @@ public sealed class InFlightCounterTests
}
/// Verifies that CapabilityInvoker increments the tracker during execution.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task CapabilityInvoker_IncrementsTracker_DuringExecution()
{
@@ -97,6 +98,7 @@ public sealed class InFlightCounterTests
}
/// Verifies that CapabilityInvoker decrements the counter on exception.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task CapabilityInvoker_ExceptionPath_DecrementsCounter()
{
@@ -119,6 +121,7 @@ public sealed class InFlightCounterTests
}
/// Verifies that CapabilityInvoker without a tracker does not throw.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task CapabilityInvoker_WithoutTracker_DoesNotThrow()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/PerCallHostResolverDispatchTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/PerCallHostResolverDispatchTests.cs
index d1acd6d2..b8cda91a 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/PerCallHostResolverDispatchTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Resilience/PerCallHostResolverDispatchTests.cs
@@ -22,13 +22,13 @@ public sealed class PerCallHostResolverDispatchTests
/// The mapping of full references to host names.
public StaticResolver(Dictionary map) => _map = map;
- /// Resolves a host name from the static mapping.
- /// The full reference to resolve.
+ ///
public string ResolveHost(string fullReference) =>
_map.TryGetValue(fullReference, out var host) ? host : string.Empty;
}
/// Verifies that a dead PLC does not open the breaker for healthy PLCs when using a per-call resolver.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task DeadPlc_DoesNotOpenBreaker_For_HealthyPlc_With_Resolver()
{
@@ -80,6 +80,7 @@ public sealed class PerCallHostResolverDispatchTests
}
/// Verifies that without a resolver, the same host shares one resilience pipeline.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task WithoutResolver_SameHost_Shares_One_Pipeline()
{
@@ -98,6 +99,7 @@ public sealed class PerCallHostResolverDispatchTests
}
/// Verifies that with a resolver, different hosts get separate resilience pipelines.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task WithResolver_TwoHosts_Get_Two_Pipelines()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Stability/MemoryRecycleTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Stability/MemoryRecycleTests.cs
index 6f17ea9c..dec3e187 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Stability/MemoryRecycleTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Stability/MemoryRecycleTests.cs
@@ -10,6 +10,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.Tests.Stability;
public sealed class MemoryRecycleTests
{
/// Verifies that Tier C hard memory breach requests supervisor recycle.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task TierC_HardBreach_RequestsSupervisorRecycle()
{
@@ -25,6 +26,7 @@ public sealed class MemoryRecycleTests
/// Verifies that Tier A and B hard memory breach never request recycle.
/// The driver tier to test.
+ /// A task that represents the asynchronous test operation.
[Theory]
[InlineData(DriverTier.A)]
[InlineData(DriverTier.B)]
@@ -40,6 +42,7 @@ public sealed class MemoryRecycleTests
}
/// Verifies that Tier C without supervisor hard breach is a no-op.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task TierC_WithoutSupervisor_HardBreach_NoOp()
{
@@ -52,6 +55,7 @@ public sealed class MemoryRecycleTests
/// Verifies that soft memory breach never requests recycle at any tier.
/// The driver tier to test.
+ /// A task that represents the asynchronous test operation.
[Theory]
[InlineData(DriverTier.A)]
[InlineData(DriverTier.B)]
@@ -69,6 +73,7 @@ public sealed class MemoryRecycleTests
/// Verifies that non-breach memory actions are no-ops.
/// The non-breach memory tracking action to test.
+ /// A task that represents the asynchronous test operation.
[Theory]
[InlineData(MemoryTrackingAction.None)]
[InlineData(MemoryTrackingAction.Warming)]
@@ -85,16 +90,14 @@ public sealed class MemoryRecycleTests
private sealed class FakeSupervisor : IDriverSupervisor
{
- /// Gets the driver instance identifier.
+ ///
public string DriverInstanceId => "fake-tier-c";
/// Gets the count of recycle operations.
public int RecycleCount { get; private set; }
/// Gets the reason from the last recycle operation.
public string? LastReason { get; private set; }
- /// Recycles the driver asynchronously.
- /// The reason for recycling.
- /// The cancellation token.
+ ///
public Task RecycleAsync(string reason, CancellationToken cancellationToken)
{
RecycleCount++;
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Stability/ScheduledRecycleSchedulerTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Stability/ScheduledRecycleSchedulerTests.cs
index 0e4f3f83..fbcb977d 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Stability/ScheduledRecycleSchedulerTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests/Stability/ScheduledRecycleSchedulerTests.cs
@@ -36,6 +36,7 @@ public sealed class ScheduledRecycleSchedulerTests
}
/// Verifies Tick before the next recycle time is a no-op.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Tick_BeforeNextRecycle_NoOp()
{
@@ -49,6 +50,7 @@ public sealed class ScheduledRecycleSchedulerTests
}
/// Verifies Tick at or after the next recycle time fires once and advances.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Tick_AtOrAfterNextRecycle_FiresOnce_AndAdvances()
{
@@ -63,6 +65,7 @@ public sealed class ScheduledRecycleSchedulerTests
}
/// Verifies RequestRecycleNow fires immediately without advancing the schedule.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task RequestRecycleNow_Fires_Immediately_WithoutAdvancingSchedule()
{
@@ -78,6 +81,7 @@ public sealed class ScheduledRecycleSchedulerTests
}
/// Verifies multiple ticks across the recycle interval each advance by one interval.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task MultipleFires_AcrossTicks_AdvanceOneIntervalEach()
{
@@ -95,7 +99,7 @@ public sealed class ScheduledRecycleSchedulerTests
/// Fake driver supervisor for testing.
private sealed class FakeSupervisor : IDriverSupervisor
{
- /// Gets the driver instance ID.
+ ///
public string DriverInstanceId => "tier-c-fake";
/// Gets the number of times RecycleAsync was called.
@@ -104,10 +108,7 @@ public sealed class ScheduledRecycleSchedulerTests
/// Gets the reason from the most recent recycle call.
public string? LastReason { get; private set; }
- /// Simulates a driver recycle operation.
- /// The reason for the recycle.
- /// Cancellation token.
- /// A completed task.
+ ///
public Task RecycleAsync(string reason, CancellationToken cancellationToken)
{
RecycleCount++;
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/FakeUpstream.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/FakeUpstream.cs
index b19aea0d..8529e678 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/FakeUpstream.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/FakeUpstream.cs
@@ -42,16 +42,13 @@ public sealed class FakeUpstream : ITagUpstreamSource
}
}
- /// Reads the current value of a tag.
- /// The path to the tag.
+ ///
public DataValueSnapshot ReadTag(string path)
=> _values.TryGetValue(path, out var v)
? v
: new DataValueSnapshot(null, 0x80340000u, null, DateTime.UtcNow);
- /// Subscribes to tag value changes.
- /// The path to the tag.
- /// The callback to invoke when the tag value changes.
+ ///
public IDisposable SubscribeTag(string path, Action observer)
{
var list = _subs.GetOrAdd(path, _ => []);
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/TimerTriggerSchedulerTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/TimerTriggerSchedulerTests.cs
index 40323374..ee2a21fb 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/TimerTriggerSchedulerTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/TimerTriggerSchedulerTests.cs
@@ -11,6 +11,7 @@ namespace ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests;
public sealed class TimerTriggerSchedulerTests
{
/// Verifies that timer interval causes periodic reevaluation of virtual tags.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Timer_interval_causes_periodic_reevaluation()
{
@@ -46,6 +47,7 @@ public sealed class TimerTriggerSchedulerTests
}
/// Verifies that tags without TimerInterval are not scheduled.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Tags_without_TimerInterval_not_scheduled()
{
@@ -98,6 +100,7 @@ public sealed class TimerTriggerSchedulerTests
// ----- Core.VirtualTags-007: timer ticks must not block pool threads and must skip when prior tick is still running -----
/// Verifies that tick is skipped when the prior tick for the same group is still running.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Tick_skips_when_prior_tick_for_the_same_group_is_still_running()
{
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/VirtualTagEngineTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/VirtualTagEngineTests.cs
index c2598f3d..9674535e 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/VirtualTagEngineTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/VirtualTagEngineTests.cs
@@ -32,6 +32,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that a simple virtual tag script can read an upstream tag and return a coerced value.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Simple_script_reads_upstream_and_returns_coerced_value()
{
@@ -52,6 +53,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that an upstream tag change triggers a cascade re-evaluation through two levels of dependent virtual tags.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Upstream_change_triggers_cascade_through_two_levels()
{
@@ -84,6 +86,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that a circular dependency among virtual tags is rejected at load time.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Cycle_in_virtual_tags_rejected_at_Load()
{
@@ -98,6 +101,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that script compilation errors surface at load time with all failures aggregated.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Script_compile_error_surfaces_at_Load_with_all_failures()
{
@@ -116,6 +120,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that a runtime exception in one virtual tag's script is isolated and does not affect other tags.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Script_runtime_exception_isolates_to_owning_tag()
{
@@ -138,6 +143,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that script timeout is mapped to BadInternalError status without killing the engine.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Timeout_maps_to_BadInternalError_without_killing_the_engine()
{
@@ -159,6 +165,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that subscribers receive notifications when the engine emits value changes.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Subscribers_receive_engine_emitted_changes()
{
@@ -180,6 +187,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that the historize flag routes virtual tag values to the history writer.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Historize_flag_routes_to_history_writer()
{
@@ -202,6 +210,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that upstream pushes are ignored when change-driven is false.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Change_driven_false_ignores_upstream_push()
{
@@ -224,6 +233,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that reloading the engine replaces existing tags and resubscribes to upstream sources cleanly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Reload_replaces_existing_tags_and_resubscribes_cleanly()
{
@@ -248,6 +258,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that disposing the engine releases all upstream subscriptions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Dispose_releases_upstream_subscriptions()
{
@@ -264,6 +275,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that SetVirtualTag called within a script updates the target and triggers observers.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SetVirtualTag_within_script_updates_target_and_triggers_observers()
{
@@ -288,6 +300,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that SetVirtualTag within a script cascades to change-triggered dependents of the written tag.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SetVirtualTag_within_script_cascades_to_dependents_of_the_written_tag()
{
@@ -321,6 +334,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that type coercion from script double to configured int32 works correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Type_coercion_from_script_double_to_config_int32()
{
@@ -339,6 +353,7 @@ public sealed class VirtualTagEngineTests
// ----- Core.VirtualTags-012: previously-missing coverage -----
/// Verifies that the AreInputsReady guard publishes BadWaitingForInitialData when upstream tags have bad status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AreInputsReady_guard_publishes_BadWaitingForInitialData_when_upstream_is_bad()
{
@@ -361,6 +376,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that the AreInputsReady guard recovers when an upstream tag transitions from bad to good status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task AreInputsReady_guard_publishes_BadWaitingForInitialData_then_recovers_when_upstream_becomes_good()
{
@@ -386,6 +402,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that SetVirtualTag cascades to change-triggered dependents.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SetVirtualTag_cascades_to_change_triggered_dependent()
{
@@ -417,6 +434,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that SetVirtualTag calls targeting unregistered paths are caught at load time.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SetVirtualTag_on_non_registered_path_is_caught_at_Load()
{
@@ -441,6 +459,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that EvaluateOneAsync throws ArgumentException when called for an unregistered path.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task EvaluateOneAsync_throws_ArgumentException_for_unregistered_path()
{
@@ -453,6 +472,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that a type coercion failure maps to BadInternalError status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CoerceResult_failure_maps_to_BadInternalError()
{
@@ -475,6 +495,7 @@ public sealed class VirtualTagEngineTests
// ----- Core.VirtualTags-011: Writes target validation at Load time -----
/// Verifies that Load rejects scripts that write to unregistered virtual tag paths.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Load_rejects_script_writing_to_unregistered_virtual_tag_path()
{
@@ -499,6 +520,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that Load accepts scripts that write to registered virtual tag paths.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Load_accepts_script_writing_to_registered_virtual_tag_path()
{
@@ -559,6 +581,7 @@ public sealed class VirtualTagEngineTests
// ----- Core.VirtualTags-004: CoerceResult default arm leaks uncoerced values -----
/// Verifies that CoerceResult correctly handles Int16, UInt16, UInt32, and UInt64 types.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task CoerceResult_handles_Int16_UInt16_UInt32_UInt64()
{
@@ -588,6 +611,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that Load rejects virtual tag definitions with unsupported DriverDataType values.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Load_rejects_definition_with_unsupported_DriverDataType()
{
@@ -608,6 +632,7 @@ public sealed class VirtualTagEngineTests
}
/// Verifies that Load rejects duplicate virtual tag paths with an aggregated error message.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Load_rejects_duplicate_path_with_aggregated_error()
{
@@ -684,9 +709,7 @@ public sealed class VirtualTagEngineTests
/// The list to store recorded history entries.
public TestHistory(List<(string, DataValueSnapshot)> buf) => _buf = buf;
- /// Records a virtual tag path and value snapshot to the history buffer.
- /// The virtual tag path.
- /// The data value snapshot to record.
+ ///
public void Record(string path, DataValueSnapshot value)
{
lock (_buf) { _buf.Add((path, value)); }
diff --git a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/VirtualTagSourceTests.cs b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/VirtualTagSourceTests.cs
index c5bbd6aa..87ad4adb 100644
--- a/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/VirtualTagSourceTests.cs
+++ b/tests/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags.Tests/VirtualTagSourceTests.cs
@@ -28,6 +28,7 @@ public sealed class VirtualTagSourceTests
}
/// Verifies that ReadAsync returns cached engine values.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_returns_engine_cached_values()
{
@@ -42,6 +43,7 @@ public sealed class VirtualTagSourceTests
}
/// Verifies that unknown paths return Bad status quality.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadAsync_unknown_path_returns_Bad_quality()
{
@@ -52,6 +54,7 @@ public sealed class VirtualTagSourceTests
}
/// Verifies that subscribe fires the initial data callback immediately.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_fires_initial_data_callback()
{
@@ -75,6 +78,7 @@ public sealed class VirtualTagSourceTests
}
/// Verifies that subscription fires on upstream changes via engine cascade.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task SubscribeAsync_fires_on_upstream_change_via_engine_cascade()
{
@@ -101,6 +105,7 @@ public sealed class VirtualTagSourceTests
}
/// Verifies that unsubscribe stops further event emissions.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UnsubscribeAsync_stops_further_events()
{
@@ -123,6 +128,7 @@ public sealed class VirtualTagSourceTests
}
/// Verifies that null arguments are rejected.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Null_arguments_rejected()
{
diff --git a/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/CommandCancellationTests.cs b/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/CommandCancellationTests.cs
index af5bd63d..74bd87f6 100644
--- a/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/CommandCancellationTests.cs
+++ b/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/CommandCancellationTests.cs
@@ -19,6 +19,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests;
public sealed class CommandCancellationTests
{
/// Verifies that probe command gracefully handles cancellation during initialization.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task ProbeCommand_swallows_cancellation_during_initialize()
{
@@ -31,6 +32,7 @@ public sealed class CommandCancellationTests
}
/// Verifies that read command gracefully handles cancellation during initialization.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task ReadCommand_swallows_cancellation_during_initialize()
{
@@ -49,6 +51,7 @@ public sealed class CommandCancellationTests
}
/// Verifies that write command gracefully handles cancellation during initialization.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task WriteCommand_swallows_cancellation_during_initialize()
{
diff --git a/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/ModbusCommandBaseTests.cs b/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/ModbusCommandBaseTests.cs
index c83b5c04..960cb1d3 100644
--- a/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/ModbusCommandBaseTests.cs
+++ b/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/ModbusCommandBaseTests.cs
@@ -28,6 +28,7 @@ public sealed class ModbusCommandBaseTests
/// Invokes BuildOptions with the given tags.
/// The list of tag definitions to build options for.
+ /// The produced by .
public ModbusDriverOptions Invoke(IReadOnlyList tags) => BuildOptions(tags);
/// Invokes ValidateEndpoint.
diff --git a/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/WriteCommandRegionValidationTests.cs b/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/WriteCommandRegionValidationTests.cs
index 99e5176d..b20b24d2 100644
--- a/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/WriteCommandRegionValidationTests.cs
+++ b/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/WriteCommandRegionValidationTests.cs
@@ -21,6 +21,7 @@ public sealed class WriteCommandRegionValidationTests
/// The read-only Modbus region to attempt a write against.
/// The data type used in the write attempt.
/// The raw string value supplied to the write command.
+ /// A task that represents the asynchronous test operation.
[Theory]
[InlineData(ModbusRegion.DiscreteInputs, ModbusDataType.Bool, "0")]
[InlineData(ModbusRegion.InputRegisters, ModbusDataType.UInt16, "1")]
@@ -44,6 +45,7 @@ public sealed class WriteCommandRegionValidationTests
/// Verifies that Coils region requires Bool data type (Driver.Modbus.Cli-002).
/// The non-Bool data type that should be rejected for the Coils region.
+ /// A task that represents the asynchronous test operation.
[Theory]
[InlineData(ModbusDataType.UInt16)]
[InlineData(ModbusDataType.Int16)]
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipReadSmokeTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipReadSmokeTests.cs
index a6b57fa5..7ccfa6b8 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipReadSmokeTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbCipReadSmokeTests.cs
@@ -21,6 +21,7 @@ public sealed class AbCipReadSmokeTests
/// Verifies that the driver can read a seeded DInt value from an AB server.
/// The AB server profile to test against.
+ /// A task that represents the asynchronous operation.
[AbServerTheory]
[MemberData(nameof(Profiles))]
public async Task Driver_reads_seeded_DInt_from_ab_server(AbServerProfile profile)
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbServerFixture.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbServerFixture.cs
index f9b23d61..8cf87854 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbServerFixture.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/AbServerFixture.cs
@@ -55,9 +55,11 @@ public sealed class AbServerFixture : IAsyncLifetime
}
}
- ///
+ /// Initializes the fixture asynchronously (no-op for this fixture).
+ /// A completed value task.
public ValueTask InitializeAsync() => ValueTask.CompletedTask;
- ///
+ /// Disposes the fixture asynchronously (no-op for this fixture).
+ /// A completed value task.
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
///
@@ -65,6 +67,7 @@ public sealed class AbServerFixture : IAsyncLifetime
/// /
/// to decide whether to skip tests on a fresh clone without a running container.
///
+ /// if the server is reachable; otherwise.
public static bool IsServerAvailable() =>
TcpProbe(ResolveHost(), ResolvePort());
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateAlmdTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateAlmdTests.cs
index 193c475d..9ca940cf 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateAlmdTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateAlmdTests.cs
@@ -40,6 +40,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests.Emulate;
public sealed class AbCipEmulateAlmdTests
{
/// Verifies that real ALMD raise fires OnAlarmEvent through the driver projection.
+ /// A task that represents the asynchronous operation.
[AbServerFact]
public async Task Real_ALMD_raise_fires_OnAlarmEvent_through_the_driver_projection()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateUdtReadTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateUdtReadTests.cs
index e36919bd..6d7302f8 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateUdtReadTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests/Emulate/AbCipEmulateUdtReadTests.cs
@@ -38,6 +38,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests.Emulate;
public sealed class AbCipEmulateUdtReadTests
{
/// Verifies that reading a whole UDT decodes each member at its template object offset.
+ /// A task that represents the asynchronous operation.
[AbServerFact]
public async Task WholeUdt_read_decodes_each_member_at_its_Template_Object_offset()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipAlarmProjectionTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipAlarmProjectionTests.cs
index 12180d34..6ede3807 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipAlarmProjectionTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipAlarmProjectionTests.cs
@@ -49,6 +49,7 @@ public sealed class AbCipAlarmProjectionTests
}
/// Verifies that disabled alarm projection returns a valid handle but does not poll.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task FeatureFlag_Off_SubscribeAlarms_Returns_Handle_But_Never_Polls()
{
@@ -76,6 +77,7 @@ public sealed class AbCipAlarmProjectionTests
}
/// Verifies that enabled alarm projection starts polling and fires raise event on 0-to-1 transition.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task FeatureFlag_On_Subscribe_Starts_Polling_And_Fires_Raise_On_0_to_1()
{
@@ -120,6 +122,7 @@ public sealed class AbCipAlarmProjectionTests
}
/// Verifies that alarm clear event fires on 1-to-0 transition.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Clear_Event_Fires_On_1_to_0_Transition()
{
@@ -161,6 +164,7 @@ public sealed class AbCipAlarmProjectionTests
}
/// Verifies that unsubscribing stops the alarm poll loop.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Unsubscribe_Stops_The_Poll_Loop()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipBoolInDIntRmwTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipBoolInDIntRmwTests.cs
index ad0f73c2..40fdcfb7 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipBoolInDIntRmwTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipBoolInDIntRmwTests.cs
@@ -19,6 +19,7 @@ public sealed class AbCipBoolInDIntRmwTests
}
/// Verifies that bit set reads parent, ORs bit, and writes back.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Bit_set_reads_parent_ORs_bit_writes_back()
{
@@ -50,6 +51,7 @@ public sealed class AbCipBoolInDIntRmwTests
}
/// Verifies that bit clear preserves other bits.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Bit_clear_preserves_other_bits()
{
@@ -73,6 +75,7 @@ public sealed class AbCipBoolInDIntRmwTests
}
/// Verifies that concurrent bit writes to same parent compose correctly.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Concurrent_bit_writes_to_same_parent_compose_correctly()
{
@@ -98,6 +101,7 @@ public sealed class AbCipBoolInDIntRmwTests
}
/// Verifies that bit writes to different parents each get their own runtime.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Bit_writes_to_different_parents_each_get_own_runtime()
{
@@ -125,6 +129,7 @@ public sealed class AbCipBoolInDIntRmwTests
}
/// Verifies that repeat bit writes reuse one parent runtime.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Repeat_bit_writes_reuse_one_parent_runtime()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverCodeReviewRegressionTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverCodeReviewRegressionTests.cs
index 477a6bb6..6397ae44 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverCodeReviewRegressionTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverCodeReviewRegressionTests.cs
@@ -19,6 +19,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
// ---- Driver.AbCip-001 — ReinitializeAsync must apply a changed config JSON ----
/// Tests that InitializeAsync applies devices and tags from the config JSON.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InitializeAsync_applies_devices_and_tags_from_the_config_json()
{
@@ -40,6 +41,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
}
/// Tests that ReinitializeAsync with changed config JSON picks up the new device.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReinitializeAsync_with_a_changed_config_json_picks_up_the_new_device()
{
@@ -63,6 +65,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
}
/// Tests that InitializeAsync with blank JSON keeps construction-time options.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InitializeAsync_with_blank_json_keeps_construction_time_options()
{
@@ -82,6 +85,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
// ---- Driver.AbCip-003 — declaration-only whole-UDT grouping is opt-in ----
/// Tests that whole UDT grouping is off by default so members read per tag.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Whole_udt_grouping_is_off_by_default_so_members_read_per_tag()
{
@@ -137,6 +141,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
// ---- Driver.AbCip-008 — ShutdownAsync awaits probe loops; reads are concurrency-safe ----
/// Tests that ShutdownAsync awaits the probe loop before returning.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ShutdownAsync_awaits_the_probe_loop_before_returning()
{
@@ -162,6 +167,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
}
/// Tests that ShutdownAsync is idempotent.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ShutdownAsync_is_idempotent()
{
@@ -176,6 +182,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
}
/// Tests that concurrent first reads of the same tag do not corrupt the runtime cache.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Concurrent_first_reads_of_the_same_tag_do_not_corrupt_the_runtime_cache()
{
@@ -217,6 +224,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
}
/// Tests that read UDInt tag returns uint value not negative-wrapped int.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Read_UDInt_tag_returns_uint_value_not_negative_wrapped_int()
{
@@ -243,6 +251,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
// ---- Driver.AbCip-005 — Structure parent not registered; duplicate key check ----
/// Tests that structure parent tag read returns BadNotSupported not Good null.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Structure_parent_tag_read_returns_BadNotSupported_not_Good_null()
{
@@ -318,6 +327,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
// ---- Driver.AbCip-010 — stale runtime evicted on failure ----
/// Tests that read failure evicts runtime so next read creates fresh handle.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Read_failure_evicts_runtime_so_next_read_creates_fresh_handle()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverDiscoveryTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverDiscoveryTests.cs
index 7a1b3ac5..9d222743 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverDiscoveryTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverDiscoveryTests.cs
@@ -10,6 +10,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests;
public sealed class AbCipDriverDiscoveryTests
{
/// Verifies that pre-declared tags emit as variables under device folder.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task PreDeclared_tags_emit_as_variables_under_device_folder()
{
@@ -35,6 +36,7 @@ public sealed class AbCipDriverDiscoveryTests
}
/// Verifies that device folder display name falls back to host address when not provided.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Device_folder_displayname_falls_back_to_host_address()
{
@@ -52,6 +54,7 @@ public sealed class AbCipDriverDiscoveryTests
}
/// Verifies that pre-declared system tags are filtered out.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task PreDeclared_system_tags_are_filtered_out()
{
@@ -74,6 +77,7 @@ public sealed class AbCipDriverDiscoveryTests
}
/// Verifies that tags for mismatched devices are ignored.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Tags_for_mismatched_device_are_ignored()
{
@@ -91,6 +95,7 @@ public sealed class AbCipDriverDiscoveryTests
}
/// Verifies that controller enumeration adds tags under Discovered folder.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Controller_enumeration_adds_tags_under_Discovered_folder()
{
@@ -114,6 +119,7 @@ public sealed class AbCipDriverDiscoveryTests
}
/// Verifies that controller enumeration honours system tag hint and filter.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Controller_enumeration_honours_system_tag_hint_and_filter()
{
@@ -136,6 +142,7 @@ public sealed class AbCipDriverDiscoveryTests
}
/// Verifies that controller enumeration ReadOnly flag surfaces ViewOnly classification.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Controller_enumeration_ReadOnly_surfaces_ViewOnly_classification()
{
@@ -156,6 +163,7 @@ public sealed class AbCipDriverDiscoveryTests
}
/// Verifies that controller enumeration receives correct device parameters.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Controller_enumeration_receives_correct_device_params()
{
@@ -236,6 +244,7 @@ public sealed class AbCipDriverDiscoveryTests
}
/// Verifies that FlushOptionalCachesAsync clears the template cache.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task FlushOptionalCachesAsync_clears_template_cache()
{
@@ -257,39 +266,29 @@ public sealed class AbCipDriverDiscoveryTests
/// Gets the list of recorded variables.
public List<(string BrowseName, DriverAttributeInfo Info)> Variables { get; } = new();
- /// Records a folder node.
- /// The browse name of the folder.
- /// The display name of the folder.
+ ///
public IAddressSpaceBuilder Folder(string browseName, string displayName)
{ Folders.Add((browseName, displayName)); return this; }
- /// Records a variable node.
- /// The browse name of the variable.
- /// The display name of the variable.
- /// The attribute information for the variable.
+ ///
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo info)
{ Variables.Add((browseName, info)); return new Handle(info.FullName); }
- /// Adds a property (no-op in test).
- /// Property name (unused in test).
- /// Property data type (unused in test).
- /// Property value (unused in test).
+ ///
public void AddProperty(string _, DriverDataType __, object? ___) { }
/// Test variable handle.
private sealed class Handle(string fullRef) : IVariableHandle
{
- /// Gets the full reference of the variable.
+ ///
public string FullReference => fullRef;
- /// Marks the variable as an alarm condition.
- /// The alarm condition information.
+ ///
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info) => new NullSink();
}
/// Null sink for alarm conditions.
private sealed class NullSink : IAlarmConditionSink
{
- /// Handles alarm transition (no-op).
- /// The alarm event arguments.
+ ///
public void OnTransition(AlarmEventArgs args) { }
}
}
@@ -303,15 +302,13 @@ public sealed class AbCipDriverDiscoveryTests
/// Initializes a new instance of the FakeEnumeratorFactory.
/// The tags to enumerate.
public FakeEnumeratorFactory(params AbCipDiscoveredTag[] tags) => _tags = tags;
- /// Creates a new fake enumerator.
+ ///
public IAbCipTagEnumerator Create() => new FakeEnumerator(this);
/// Fake tag enumerator for testing.
private sealed class FakeEnumerator(FakeEnumeratorFactory outer) : IAbCipTagEnumerator
{
- /// Enumerates discovered tags asynchronously.
- /// The device parameters for enumeration.
- /// The cancellation token.
+ ///
public async IAsyncEnumerable EnumerateAsync(
AbCipTagCreateParams deviceParams,
[EnumeratorCancellation] CancellationToken cancellationToken)
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverReadTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverReadTests.cs
index e37b1a0f..79506f79 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverReadTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverReadTests.cs
@@ -22,6 +22,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that an unknown reference maps to BadNodeIdUnknown status.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Unknown_reference_maps_to_BadNodeIdUnknown()
{
@@ -35,6 +36,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that a tag on an unknown device maps to BadNodeIdUnknown status.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Tag_on_unknown_device_maps_to_BadNodeIdUnknown()
{
@@ -52,6 +54,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that a successful DInt read returns Good status with the correct value.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Successful_DInt_read_returns_Good_with_value()
{
@@ -71,6 +74,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that repeated reads reuse the runtime without reinitializing.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Repeat_read_reuses_runtime_without_reinitialise()
{
@@ -88,6 +92,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that non-zero libplctag status is mapped via AbCipStatusMapper.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task NonZero_libplctag_status_maps_via_AbCipStatusMapper()
{
@@ -103,6 +108,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that an exception during read surfaces BadCommunicationError status.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Exception_during_read_surfaces_BadCommunicationError()
{
@@ -119,6 +125,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that batched reads preserve order and per-tag status.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Batched_reads_preserve_order_and_per_tag_status()
{
@@ -144,6 +151,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that a successful read marks health as Healthy.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Successful_read_marks_health_Healthy()
{
@@ -158,6 +166,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that tag creation parameters are built correctly from device and profile.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task TagCreateParams_are_built_from_device_and_profile()
{
@@ -176,6 +185,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that cancellation propagates from read operations.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Cancellation_propagates_from_read()
{
@@ -194,6 +204,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that ShutdownAsync disposes each tag runtime.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ShutdownAsync_disposes_each_tag_runtime()
{
@@ -211,6 +222,7 @@ public sealed class AbCipDriverReadTests
}
/// Verifies that initialization failure disposes the tag and surfaces communication error.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Initialize_failure_disposes_tag_and_surfaces_communication_error()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverTests.cs
index 235e4390..3f52ad9a 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverTests.cs
@@ -19,6 +19,7 @@ public sealed class AbCipDriverTests
}
/// Verifies InitializeAsync with no devices succeeds and marks driver healthy.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InitializeAsync_with_empty_devices_succeeds_and_marks_healthy()
{
@@ -28,6 +29,7 @@ public sealed class AbCipDriverTests
}
/// Verifies InitializeAsync registers devices with their respective PLC family profiles.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InitializeAsync_registers_each_device_with_its_family_profile()
{
@@ -48,6 +50,7 @@ public sealed class AbCipDriverTests
}
/// Verifies InitializeAsync rejects malformed host addresses and faults the driver.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InitializeAsync_with_malformed_host_address_faults()
{
@@ -62,6 +65,7 @@ public sealed class AbCipDriverTests
}
/// Verifies ShutdownAsync clears devices and marks driver state unknown.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ShutdownAsync_clears_devices_and_marks_unknown()
{
@@ -79,6 +83,7 @@ public sealed class AbCipDriverTests
}
/// Verifies ReinitializeAsync stops and restarts all devices.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReinitializeAsync_cycles_devices()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverWholeUdtReadTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverWholeUdtReadTests.cs
index 56f48150..d3918307 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverWholeUdtReadTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverWholeUdtReadTests.cs
@@ -35,6 +35,7 @@ public sealed class AbCipDriverWholeUdtReadTests
]);
/// Verifies that multiple members of the same UDT trigger only one parent read.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Two_members_of_same_udt_trigger_one_parent_read()
{
@@ -55,6 +56,7 @@ public sealed class AbCipDriverWholeUdtReadTests
}
/// Verifies that each UDT member is decoded at its correct offset.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Each_member_decodes_at_its_own_offset()
{
@@ -81,6 +83,7 @@ public sealed class AbCipDriverWholeUdtReadTests
}
/// Verifies that parent read failure marks all grouped members as Bad.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Parent_read_failure_stamps_every_grouped_member_Bad()
{
@@ -101,6 +104,7 @@ public sealed class AbCipDriverWholeUdtReadTests
}
/// Verifies that mixed batches group UDT members and fall back to atomic reads.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Mixed_batch_groups_udt_and_falls_back_atomics()
{
@@ -121,6 +125,7 @@ public sealed class AbCipDriverWholeUdtReadTests
}
/// Verifies that a single UDT member uses the per-tag read path rather than grouping.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Single_member_of_Udt_uses_per_tag_read_path()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverWriteTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverWriteTests.cs
index 9340dec3..d3610ba7 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverWriteTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipDriverWriteTests.cs
@@ -21,6 +21,7 @@ public sealed class AbCipDriverWriteTests
}
/// Verifies that unknown reference maps to BadNodeIdUnknown status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Unknown_reference_maps_to_BadNodeIdUnknown()
{
@@ -34,6 +35,7 @@ public sealed class AbCipDriverWriteTests
}
/// Verifies that non-writable tags map to BadNotWritable status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Non_writable_tag_maps_to_BadNotWritable()
{
@@ -48,6 +50,7 @@ public sealed class AbCipDriverWriteTests
}
/// Verifies that successful DInt writes encode and flush values.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Successful_DInt_write_encodes_and_flushes()
{
@@ -64,6 +67,7 @@ public sealed class AbCipDriverWriteTests
}
/// Verifies that bit-in-DInt writes succeed via read-modify-write.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Bit_in_dint_write_now_succeeds_via_RMW()
{
@@ -85,6 +89,7 @@ public sealed class AbCipDriverWriteTests
}
/// Verifies that non-zero libplctag status after write maps correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Non_zero_libplctag_status_after_write_maps_via_AbCipStatusMapper()
{
@@ -100,6 +105,7 @@ public sealed class AbCipDriverWriteTests
}
/// Verifies that type mismatch surfaces BadTypeMismatch status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Type_mismatch_surfaces_BadTypeMismatch()
{
@@ -126,6 +132,7 @@ public sealed class AbCipDriverWriteTests
}
/// Verifies that overflow surfaces BadOutOfRange status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Overflow_surfaces_BadOutOfRange()
{
@@ -144,6 +151,7 @@ public sealed class AbCipDriverWriteTests
}
/// Verifies that exceptions during write surface BadCommunicationError.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Exception_during_write_surfaces_BadCommunicationError()
{
@@ -160,6 +168,7 @@ public sealed class AbCipDriverWriteTests
}
/// Verifies that batch write preserves order across success and failure.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Batch_preserves_order_across_success_and_failure()
{
@@ -192,6 +201,7 @@ public sealed class AbCipDriverWriteTests
}
/// Verifies that cancellation propagates from write operations.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Cancellation_propagates_from_write()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipFetchUdtShapeTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipFetchUdtShapeTests.cs
index 2d0554a8..03327917 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipFetchUdtShapeTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipFetchUdtShapeTests.cs
@@ -25,11 +25,7 @@ public sealed class AbCipFetchUdtShapeTests
/// Gets the last template ID read.
public uint LastTemplateId { get; private set; }
- /// Reads the template data for the specified device and template ID.
- /// The device parameters.
- /// The template instance ID.
- /// The cancellation token.
- /// A task that returns the template response bytes.
+ ///
public Task ReadAsync(AbCipTagCreateParams deviceParams, uint templateInstanceId, CancellationToken ct)
{
ReadCount++;
@@ -50,8 +46,7 @@ public sealed class AbCipFetchUdtShapeTests
/// Gets or sets an optional customization function for reader creation.
public Func? Customise { get; set; }
- /// Creates a new template reader.
- /// The created reader.
+ ///
public IAbCipTemplateReader Create()
{
var r = Customise?.Invoke() ?? new FakeTemplateReader();
@@ -93,6 +88,7 @@ public sealed class AbCipFetchUdtShapeTests
}
/// Verifies that FetchUdtShapeAsync decodes a blob and caches the result.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task FetchUdtShapeAsync_decodes_blob_and_caches_result()
{
@@ -123,6 +119,7 @@ public sealed class AbCipFetchUdtShapeTests
}
/// Verifies that different template IDs result in separate fetch operations.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task FetchUdtShapeAsync_different_templateIds_each_fetch()
{
@@ -154,6 +151,7 @@ public sealed class AbCipFetchUdtShapeTests
}
/// Verifies that FetchUdtShapeAsync returns null for an unknown device.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task FetchUdtShapeAsync_unknown_device_returns_null()
{
@@ -170,6 +168,7 @@ public sealed class AbCipFetchUdtShapeTests
}
/// Verifies that a decode failure returns null and does not cache the result.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task FetchUdtShapeAsync_decode_failure_returns_null_and_does_not_cache()
{
@@ -193,6 +192,7 @@ public sealed class AbCipFetchUdtShapeTests
}
/// Verifies that a reader exception returns null.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task FetchUdtShapeAsync_reader_exception_returns_null()
{
@@ -211,6 +211,7 @@ public sealed class AbCipFetchUdtShapeTests
}
/// Verifies that FlushOptionalCachesAsync empties the template cache.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task FlushOptionalCachesAsync_empties_template_cache()
{
@@ -241,11 +242,7 @@ public sealed class AbCipFetchUdtShapeTests
/// Test implementation of IAbCipTemplateReader that throws on read.
private sealed class ThrowingTemplateReader : IAbCipTemplateReader
{
- /// Throws an exception when read is attempted.
- /// The device parameters.
- /// The template ID.
- /// The cancellation token.
- /// Never returns; throws instead.
+ ///
public Task ReadAsync(AbCipTagCreateParams p, uint id, CancellationToken ct) =>
throw new InvalidOperationException("fake read failure");
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipHostProbeTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipHostProbeTests.cs
index 4e8366ec..a52b9464 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipHostProbeTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipHostProbeTests.cs
@@ -10,6 +10,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests;
public sealed class AbCipHostProbeTests
{
/// Verifies that GetHostStatuses returns one entry per configured device.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task GetHostStatuses_returns_one_entry_per_device()
{
@@ -31,6 +32,7 @@ public sealed class AbCipHostProbeTests
}
/// Verifies that a successful probe read transitions the host state to Running.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Probe_with_successful_read_transitions_to_Running()
{
@@ -58,6 +60,7 @@ public sealed class AbCipHostProbeTests
}
/// Verifies that a failed probe read transitions the host state to Stopped.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Probe_with_read_failure_transitions_to_Stopped()
{
@@ -87,6 +90,7 @@ public sealed class AbCipHostProbeTests
}
/// Verifies that the probe is disabled when the Enabled option is false.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Probe_disabled_when_Enabled_is_false()
{
@@ -108,6 +112,7 @@ public sealed class AbCipHostProbeTests
}
/// Verifies that the probe is skipped when ProbeTagPath is null.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Probe_skipped_when_ProbeTagPath_is_null()
{
@@ -125,6 +130,7 @@ public sealed class AbCipHostProbeTests
}
/// Verifies that the probe loops across multiple devices independently.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Probe_loops_across_multiple_devices_independently()
{
@@ -162,6 +168,7 @@ public sealed class AbCipHostProbeTests
// ---- IPerCallHostResolver ----
/// Verifies that ResolveHost returns the declared device for a known tag.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ResolveHost_returns_declared_device_for_known_tag()
{
@@ -186,6 +193,7 @@ public sealed class AbCipHostProbeTests
}
/// Verifies that ResolveHost falls back to the first device for an unknown tag reference.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ResolveHost_falls_back_to_first_device_for_unknown_reference()
{
@@ -200,6 +208,7 @@ public sealed class AbCipHostProbeTests
}
/// Verifies that ResolveHost falls back to the driver instance ID when no devices are configured.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ResolveHost_falls_back_to_DriverInstanceId_when_no_devices()
{
@@ -210,6 +219,7 @@ public sealed class AbCipHostProbeTests
}
/// Verifies that ResolveHost for a UDT member walks to the synthesized definition.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ResolveHost_for_UDT_member_walks_to_synthesised_definition()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipLoggingTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipLoggingTests.cs
index 73f2f5b8..2e22f620 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipLoggingTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipLoggingTests.cs
@@ -36,6 +36,7 @@ public sealed class AbCipLoggingTests
}
/// Verifies that ProbeLoop logs when an exception is swallowed.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ProbeLoop_logs_when_an_exception_is_swallowed()
{
@@ -79,6 +80,7 @@ public sealed class AbCipLoggingTests
}
/// Verifies that ReadFailure logs at warning level.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadFailure_logs_at_warning_level()
{
@@ -106,6 +108,7 @@ public sealed class AbCipLoggingTests
}
/// Verifies that ReadException logs at warning level.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ReadException_logs_at_warning_level()
{
@@ -137,6 +140,7 @@ public sealed class AbCipLoggingTests
}
/// Verifies that InitializeAsync warns when probe is enabled but ProbeTagPath is blank.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InitializeAsync_warns_when_probe_is_enabled_but_ProbeTagPath_is_blank()
{
@@ -164,6 +168,7 @@ public sealed class AbCipLoggingTests
}
/// Verifies that InitializeAsync does not warn when probe is disabled.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InitializeAsync_does_not_warn_when_probe_is_disabled()
{
@@ -191,9 +196,11 @@ public sealed class AbCipLoggingTests
/// Begins a scope (stub implementation).
/// The type of the scope state.
/// The scope state.
+ /// A no-op disposable scope.
public IDisposable BeginScope(TState state) where TState : notnull => NullScope.Instance;
/// Checks if logging is enabled (always true).
/// The log level to check.
+ /// true always — this capturing logger accepts every log level.
public bool IsEnabled(LogLevel logLevel) => true;
/// Logs an entry and captures it.
/// The type of the log state.
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipPerDeviceConnectionOptionsTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipPerDeviceConnectionOptionsTests.cs
index c290672f..14e2d770 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipPerDeviceConnectionOptionsTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipPerDeviceConnectionOptionsTests.cs
@@ -21,6 +21,7 @@ public sealed class AbCipPerDeviceConnectionOptionsTests
private const string Device = "ab://10.0.0.5/1,0";
/// Verifies that per-device AllowPacking override is forwarded to tag creation parameters.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Device_AllowPacking_override_is_forwarded_to_tag_create_params()
{
@@ -40,6 +41,7 @@ public sealed class AbCipPerDeviceConnectionOptionsTests
}
/// Verifies that AllowPacking defaults inherit from the family profile when not overridden.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Device_AllowPacking_default_inherits_from_family_profile()
{
@@ -61,6 +63,7 @@ public sealed class AbCipPerDeviceConnectionOptionsTests
}
/// Verifies that Micro800 devices have AllowPacking defaulting to false from the family profile.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Micro800_default_AllowPacking_is_false_from_family_profile()
{
@@ -81,6 +84,7 @@ public sealed class AbCipPerDeviceConnectionOptionsTests
}
/// Verifies that per-device ConnectionSize override is forwarded to tag creation parameters.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Device_ConnectionSize_override_is_forwarded_to_tag_create_params()
{
@@ -99,6 +103,7 @@ public sealed class AbCipPerDeviceConnectionOptionsTests
}
/// Verifies that ConnectionSize defaults inherit from the family profile when not overridden.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Device_ConnectionSize_default_inherits_from_family_profile()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipPlcFamilyTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipPlcFamilyTests.cs
index 78b496c2..2c00f307 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipPlcFamilyTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipPlcFamilyTests.cs
@@ -25,6 +25,7 @@ public sealed class AbCipPlcFamilyTests
}
/// Verifies that a ControlLogix device initializes with the correct profile.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ControlLogix_device_initialises_with_correct_profile()
{
@@ -54,6 +55,7 @@ public sealed class AbCipPlcFamilyTests
}
/// Verifies that a CompactLogix device initializes with a narrow connection size.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task CompactLogix_device_initialises_with_narrow_ConnectionSize()
{
@@ -85,6 +87,7 @@ public sealed class AbCipPlcFamilyTests
}
/// Verifies that a Micro800 device with an empty CIP path parses correctly.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Micro800_device_with_empty_cip_path_parses_correctly()
{
@@ -102,6 +105,7 @@ public sealed class AbCipPlcFamilyTests
}
/// Verifies that Micro800 read operations forward the empty path to tag creation parameters.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Micro800_read_forwards_empty_path_to_tag_create_params()
{
@@ -134,6 +138,7 @@ public sealed class AbCipPlcFamilyTests
}
/// Verifies that GuardLogix safety tags surface as ViewOnly in discovery.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task GuardLogix_safety_tag_surfaces_as_ViewOnly_in_discovery()
{
@@ -160,6 +165,7 @@ public sealed class AbCipPlcFamilyTests
}
/// Verifies that GuardLogix safety tag writes are rejected even when the tag is marked Writable.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task GuardLogix_safety_tag_writes_rejected_even_when_Writable_is_true()
{
@@ -206,37 +212,27 @@ public sealed class AbCipPlcFamilyTests
/// Gets the list of variables recorded by this builder.
public List<(string BrowseName, DriverAttributeInfo Info)> Variables { get; } = new();
- /// Adds a folder to the recorded list and returns this builder for chaining.
- /// The browse name of the folder.
- /// The display name of the folder.
+ ///
public IAddressSpaceBuilder Folder(string browseName, string displayName)
{ Folders.Add((browseName, displayName)); return this; }
- /// Adds a variable to the recorded list and returns a handle.
- /// The browse name of the variable.
- /// The display name of the variable.
- /// The driver attribute information.
+ ///
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo info)
{ Variables.Add((browseName, info)); return new Handle(info.FullName); }
- /// No-op property adding operation for test compatibility.
- /// The property name.
- /// The property data type.
- /// The property value.
+ ///
public void AddProperty(string _, DriverDataType __, object? ___) { }
private sealed class Handle(string fullRef) : IVariableHandle
{
- /// Gets the full reference for this variable handle.
+ ///
public string FullReference => fullRef;
- /// Marks this variable as an alarm condition and returns a null sink.
- /// The alarm condition information.
+ ///
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info) => new NullSink();
}
private sealed class NullSink : IAlarmConditionSink
{
- /// Called when an alarm state transitions.
- /// The alarm event arguments.
+ ///
public void OnTransition(AlarmEventArgs args) { }
}
}
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipSubscriptionTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipSubscriptionTests.cs
index 1bb8c48c..811570f4 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipSubscriptionTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipSubscriptionTests.cs
@@ -21,6 +21,7 @@ public sealed class AbCipSubscriptionTests
}
/// Verifies that the initial poll raises OnDataChange events for every subscribed tag.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Initial_poll_raises_OnDataChange_for_every_tag()
{
@@ -47,6 +48,7 @@ public sealed class AbCipSubscriptionTests
}
/// Verifies that unchanged values raise OnDataChange only once (on initial poll).
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Unchanged_value_raises_only_once()
{
@@ -66,6 +68,7 @@ public sealed class AbCipSubscriptionTests
}
/// Verifies that value changes between polls raise OnDataChange events.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Value_change_between_polls_raises_OnDataChange()
{
@@ -89,6 +92,7 @@ public sealed class AbCipSubscriptionTests
}
/// Verifies that unsubscribe halts polling and no further events are raised.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Unsubscribe_halts_polling()
{
@@ -112,6 +116,7 @@ public sealed class AbCipSubscriptionTests
}
/// Verifies that polling intervals below 100ms are floored to the minimum.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Interval_below_100ms_is_floored()
{
@@ -133,6 +138,7 @@ public sealed class AbCipSubscriptionTests
}
/// Verifies that ShutdownAsync cancels all active subscriptions.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task ShutdownAsync_cancels_active_subscriptions()
{
@@ -154,6 +160,7 @@ public sealed class AbCipSubscriptionTests
}
/// Verifies that subscriptions on UDT members use the synthesized full reference.
+ /// A task that represents the asynchronous test.
[Fact]
public async Task Subscription_on_UDT_member_uses_synthesised_full_reference()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipUdtMemberTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipUdtMemberTests.cs
index fea9b9f6..412f5581 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipUdtMemberTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/AbCipUdtMemberTests.cs
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests;
public sealed class AbCipUdtMemberTests
{
/// Verifies that UDT with declared members expands to individual member variables.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UDT_with_declared_members_fans_out_to_member_variables()
{
@@ -48,6 +49,7 @@ public sealed class AbCipUdtMemberTests
}
/// Verifies that UDT members can be read via synthesised full reference paths.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UDT_members_resolvable_for_read_via_synthesised_full_reference()
{
@@ -84,6 +86,7 @@ public sealed class AbCipUdtMemberTests
}
/// Verifies that UDT member writes route through synthesised tag paths.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UDT_member_write_routes_through_synthesised_tagpath()
{
@@ -110,6 +113,7 @@ public sealed class AbCipUdtMemberTests
}
/// Verifies that UDT member read/write operations respect the Writable flag.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UDT_member_read_write_honours_member_Writable_flag()
{
@@ -135,6 +139,7 @@ public sealed class AbCipUdtMemberTests
}
/// Verifies that structure tags without declared members appear as single variables.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Structure_tag_without_members_is_emitted_as_single_variable()
{
@@ -156,6 +161,7 @@ public sealed class AbCipUdtMemberTests
}
/// Verifies that empty member lists are treated the same as null.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Empty_Members_list_is_treated_like_null()
{
@@ -174,6 +180,7 @@ public sealed class AbCipUdtMemberTests
}
/// Verifies that UDT members and flat tags can coexist in the address space.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task UDT_members_mixed_with_flat_tags_coexist()
{
@@ -209,39 +216,29 @@ public sealed class AbCipUdtMemberTests
/// Gets the collected variables.
public List<(string BrowseName, DriverAttributeInfo Info)> Variables { get; } = new();
- /// Records a folder in the address space.
- /// The browse name of the folder.
- /// The display name of the folder.
+ ///
public IAddressSpaceBuilder Folder(string browseName, string displayName)
{ Folders.Add((browseName, displayName)); return this; }
- /// Records a variable in the address space.
- /// The browse name of the variable.
- /// The display name of the variable.
- /// The driver attribute information for the variable.
+ ///
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo info)
{ Variables.Add((browseName, info)); return new Handle(info.FullName); }
- /// Records a property (stub implementation for testing).
- /// The property name (unused in this stub).
- /// The property data type (unused in this stub).
- /// The property value (unused in this stub).
+ ///
public void AddProperty(string _, DriverDataType __, object? ___) { }
/// Variable handle implementation for testing.
private sealed class Handle(string fullRef) : IVariableHandle
{
- /// Gets the full reference path.
+ ///
public string FullReference => fullRef;
- /// Marks this handle as an alarm condition.
- /// The alarm condition information.
+ ///
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info) => new NullSink();
}
/// Null alarm condition sink for testing.
private sealed class NullSink : IAlarmConditionSink
{
- /// Handles alarm transitions (stub).
- /// The alarm event arguments.
+ ///
public void OnTransition(AlarmEventArgs args) { }
}
}
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/FakeAbCipTag.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/FakeAbCipTag.cs
index 2e437a1d..0649294d 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/FakeAbCipTag.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests/FakeAbCipTag.cs
@@ -35,8 +35,7 @@ internal class FakeAbCipTag : IAbCipTagRuntime
/// The tag creation parameters.
public FakeAbCipTag(AbCipTagCreateParams createParams) => CreationParams = createParams;
- /// Increments the initialize count and simulates initialization.
- /// The cancellation token for the operation.
+ ///
public virtual Task InitializeAsync(CancellationToken cancellationToken)
{
InitializeCount++;
@@ -44,8 +43,7 @@ internal class FakeAbCipTag : IAbCipTagRuntime
return Task.CompletedTask;
}
- /// Increments the read count and simulates a read operation.
- /// The cancellation token for the operation.
+ ///
public virtual Task ReadAsync(CancellationToken cancellationToken)
{
ReadCount++;
@@ -53,20 +51,17 @@ internal class FakeAbCipTag : IAbCipTagRuntime
return Task.CompletedTask;
}
- /// Increments the write count and simulates a write operation.
- /// The cancellation token for the operation.
+ ///
public virtual Task WriteAsync(CancellationToken cancellationToken)
{
WriteCount++;
return Task.CompletedTask;
}
- /// Returns the simulated status code.
+ ///
public virtual int GetStatus() => Status;
- /// Returns the mock tag value.
- /// The data type being decoded.
- /// The optional bit index for bit operations.
+ ///
public virtual object? DecodeValue(AbCipDataType type, int? bitIndex) => Value;
///
@@ -78,20 +73,14 @@ internal class FakeAbCipTag : IAbCipTagRuntime
///
public Dictionary ValuesByOffset { get; } = new();
- /// Returns the mock value at the specified offset.
- /// The data type being decoded.
- /// The byte offset into the tag storage.
- /// The optional bit index for bit operations.
+ ///
public virtual object? DecodeValueAt(AbCipDataType type, int offset, int? bitIndex)
{
if (ValuesByOffset.TryGetValue(offset, out var v)) return v;
return offset == 0 ? Value : null;
}
- /// Encodes a value into the mock tag storage.
- /// The data type being encoded.
- /// The optional bit index for bit operations.
- /// The value to encode.
+ ///
public virtual void EncodeValue(AbCipDataType type, int? bitIndex, object? value) => Value = value;
/// Marks the tag as disposed.
@@ -106,8 +95,7 @@ internal sealed class FakeAbCipTagFactory : IAbCipTagFactory
/// Gets or sets an optional customization function to override the tag creation.
public Func? Customise { get; set; }
- /// Creates a new fake tag and indexes it by name.
- /// The tag creation parameters.
+ ///
public IAbCipTagRuntime Create(AbCipTagCreateParams createParams)
{
var fake = Customise?.Invoke(createParams) ?? new FakeAbCipTag(createParams);
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyReadSmokeTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyReadSmokeTests.cs
index 0aa29fc6..54443e3c 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyReadSmokeTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyReadSmokeTests.cs
@@ -37,6 +37,7 @@ public sealed class AbLegacyReadSmokeTests(AbLegacyServerFixture sim)
/// Verifies that the driver reads seeded N file from the AB server via PCCC.
/// The AB Legacy server profile describing the fixture endpoint.
+ /// A task that represents the asynchronous operation.
[AbLegacyTheory]
[MemberData(nameof(Profiles))]
public async Task Driver_reads_seeded_N_file_from_ab_server_PCCC(AbLegacyServerProfile profile)
@@ -73,6 +74,7 @@ public sealed class AbLegacyReadSmokeTests(AbLegacyServerFixture sim)
}
/// Verifies that SLC500 write-then-read round trip succeeds on N7 scratch register.
+ /// A task that represents the asynchronous operation.
[AbLegacyFact]
public async Task Slc500_write_then_read_round_trip_on_N7_scratch_register()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyServerFixture.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyServerFixture.cs
index 7faa0ca8..03452049 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyServerFixture.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.IntegrationTests/AbLegacyServerFixture.cs
@@ -85,9 +85,11 @@ public sealed class AbLegacyServerFixture : IAsyncLifetime
}
/// Initializes the fixture asynchronously.
+ /// A completed value task.
public ValueTask InitializeAsync() => ValueTask.CompletedTask;
/// Disposes the fixture asynchronously.
+ /// A completed value task.
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
///
@@ -96,6 +98,7 @@ public sealed class AbLegacyServerFixture : IAsyncLifetime
/// fixture logic because attribute ctors fire before the collection fixture instance
/// exists.
///
+ /// if the server endpoint is reachable; otherwise .
public static bool IsServerAvailable()
{
var (host, port) = ResolveEndpoint();
@@ -169,6 +172,7 @@ public static class KnownProfiles
/// Gets the profile for the specified PLC family.
/// The PLC family.
+ /// The server profile for the specified family.
public static AbLegacyServerProfile ForFamily(AbLegacyPlcFamily family) =>
All.FirstOrDefault(p => p.Family == family)
?? throw new ArgumentOutOfRangeException(nameof(family), family, "No integration profile for this family.");
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyBitIndexRangeTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyBitIndexRangeTests.cs
index 3fde086d..1668dad5 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyBitIndexRangeTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyBitIndexRangeTests.cs
@@ -68,6 +68,7 @@ public sealed class AbLegacyBitIndexRangeTests
AbLegacyAddress.TryParse("N7:0/-1").ShouldBeNull();
/// Verifies that bit in word RMW against L file uses 32-bit parent and high bit.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Bit_in_word_RMW_against_L_file_uses_32bit_parent_and_high_bit()
{
@@ -93,6 +94,7 @@ public sealed class AbLegacyBitIndexRangeTests
}
/// Verifies that bit in word RMW high bit 15 does not corrupt via sign extension.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Bit_in_word_RMW_high_bit_15_does_not_corrupt_via_sign_extension()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyBitRmwTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyBitRmwTests.cs
index b1ba8804..0ec16199 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyBitRmwTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyBitRmwTests.cs
@@ -9,6 +9,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests;
public sealed class AbLegacyBitRmwTests
{
/// Verifies that setting a bit reads the parent word, ORs the bit, and writes back.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Bit_set_reads_parent_word_ORs_bit_writes_back()
{
@@ -33,6 +34,7 @@ public sealed class AbLegacyBitRmwTests
}
/// Verifies that clearing a bit preserves other bits in the word.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Bit_clear_preserves_other_bits_in_N_file_word()
{
@@ -54,6 +56,7 @@ public sealed class AbLegacyBitRmwTests
}
/// Verifies that concurrent bit writes to the same word compose correctly.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Concurrent_bit_writes_to_same_word_compose_correctly()
{
@@ -79,6 +82,7 @@ public sealed class AbLegacyBitRmwTests
}
/// Verifies that repeated bit writes reuse the parent word runtime.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Repeat_bit_writes_reuse_parent_runtime()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyCapabilityTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyCapabilityTests.cs
index d9737d32..5f19af07 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyCapabilityTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyCapabilityTests.cs
@@ -12,6 +12,7 @@ public sealed class AbLegacyCapabilityTests
// ---- ITagDiscovery ----
/// Verifies that DiscoverAsync emits pre-declared tags under the device folder.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task DiscoverAsync_emits_pre_declared_tags_under_device_folder()
{
@@ -40,6 +41,7 @@ public sealed class AbLegacyCapabilityTests
// ---- ISubscribable ----
/// Verifies that Subscribe initial poll raises OnDataChange.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Subscribe_initial_poll_raises_OnDataChange()
{
@@ -66,6 +68,7 @@ public sealed class AbLegacyCapabilityTests
}
/// Verifies that Unsubscribe halts polling.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Unsubscribe_halts_polling()
{
@@ -96,6 +99,7 @@ public sealed class AbLegacyCapabilityTests
// ---- IHostConnectivityProbe ----
/// Verifies that GetHostStatuses returns one status per device.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task GetHostStatuses_returns_one_per_device()
{
@@ -114,6 +118,7 @@ public sealed class AbLegacyCapabilityTests
}
/// Verifies that Probe transitions to Running on successful read.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Probe_transitions_to_Running_on_successful_read()
{
@@ -138,6 +143,7 @@ public sealed class AbLegacyCapabilityTests
}
/// Verifies that Probe transitions to Stopped on read failure.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Probe_transitions_to_Stopped_on_read_failure()
{
@@ -162,6 +168,7 @@ public sealed class AbLegacyCapabilityTests
}
/// Verifies that Probe is disabled when ProbeAddress is null.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Probe_disabled_when_ProbeAddress_is_null()
{
@@ -180,6 +187,7 @@ public sealed class AbLegacyCapabilityTests
// ---- IPerCallHostResolver ----
/// Verifies that ResolveHost returns declared device for known tag.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ResolveHost_returns_declared_device_for_known_tag()
{
@@ -204,6 +212,7 @@ public sealed class AbLegacyCapabilityTests
}
/// Verifies that ResolveHost falls back to first device for unknown tags.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ResolveHost_falls_back_to_first_device_for_unknown()
{
@@ -218,6 +227,7 @@ public sealed class AbLegacyCapabilityTests
}
/// Verifies that ResolveHost falls back to DriverInstanceId when no devices exist.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task ResolveHost_falls_back_to_DriverInstanceId_when_no_devices()
{
@@ -243,31 +253,22 @@ public sealed class AbLegacyCapabilityTests
/// Gets list of variables created during discovery.
public List<(string BrowseName, DriverAttributeInfo Info)> Variables { get; } = new();
- /// Records folder creation.
- /// The browse name of the folder.
- /// The display name of the folder.
+ ///
public IAddressSpaceBuilder Folder(string browseName, string displayName)
{ Folders.Add((browseName, displayName)); return this; }
- /// Records variable creation.
- /// The browse name of the variable.
- /// The display name of the variable.
- /// The driver attribute information.
+ ///
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo info)
{ Variables.Add((browseName, info)); return new Handle(info.FullName); }
- /// Records property addition (stub implementation).
- /// The property name (unused).
- /// The data type (unused).
- /// The property value (unused).
+ ///
public void AddProperty(string _, DriverDataType __, object? ___) { }
private sealed class Handle(string fullRef) : IVariableHandle
{
- /// Gets the full reference of the variable.
+ ///
public string FullReference => fullRef;
- /// Marks the variable as an alarm condition.
- /// The alarm condition information.
+ ///
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info) => new NullSink();
}
/// Null sink for alarm condition transitions.
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyDisposeAndResolveHostTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyDisposeAndResolveHostTests.cs
index 1037ab08..294e5260 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyDisposeAndResolveHostTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyDisposeAndResolveHostTests.cs
@@ -18,6 +18,7 @@ public sealed class AbLegacyDisposeAndResolveHostTests
// ---- Driver.AbLegacy-011 ----
/// Verifies that Dispose performs teardown without blocking on async operations.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Dispose_runs_teardown_without_blocking_on_async_wait()
{
@@ -47,6 +48,7 @@ public sealed class AbLegacyDisposeAndResolveHostTests
}
/// Verifies that Dispose can be called multiple times without throwing.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Dispose_is_idempotent()
{
@@ -61,6 +63,7 @@ public sealed class AbLegacyDisposeAndResolveHostTests
}
/// Verifies that Dispose does not deadlock under a single-threaded synchronization context.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task Dispose_under_single_threaded_sync_context_does_not_deadlock()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyDriverTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyDriverTests.cs
index d684915c..600437d3 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyDriverTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyDriverTests.cs
@@ -19,6 +19,7 @@ public sealed class AbLegacyDriverTests
}
/// Verifies that InitializeAsync with devices assigns family profiles.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InitializeAsync_with_devices_assigns_family_profiles()
{
@@ -41,6 +42,7 @@ public sealed class AbLegacyDriverTests
}
/// Verifies that InitializeAsync with malformed host address faults.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task InitializeAsync_with_malformed_host_address_faults()
{
@@ -55,6 +57,7 @@ public sealed class AbLegacyDriverTests
}
/// Verifies that ShutdownAsync clears devices.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ShutdownAsync_clears_devices()
{
@@ -115,6 +118,7 @@ public sealed class AbLegacyDriverTests
// ---- Driver.AbLegacy-012: profile fields consumed ----
/// Verifies that EffectiveCipPath falls back to profile default when host path is empty.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task EffectiveCipPath_falls_back_to_profile_default_when_host_path_is_empty()
{
@@ -135,6 +139,7 @@ public sealed class AbLegacyDriverTests
}
/// Verifies that EffectiveCipPath preserves explicit host path.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task EffectiveCipPath_preserves_explicit_host_path()
{
@@ -154,6 +159,7 @@ public sealed class AbLegacyDriverTests
}
/// Verifies that long tag on MicroLogix device is rejected at initialization.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Long_tag_on_MicroLogix_device_rejected_at_init()
{
@@ -170,6 +176,7 @@ public sealed class AbLegacyDriverTests
}
/// Verifies that long tag on SLC 500 device is accepted.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Long_tag_on_Slc500_device_accepted()
{
@@ -186,6 +193,7 @@ public sealed class AbLegacyDriverTests
}
/// Verifies that string tag on PLC-5 device is rejected at initialization.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task String_tag_on_Plc5_device_rejected_at_init()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyLoggerInjectionTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyLoggerInjectionTests.cs
index 2167da4d..2f65b3ed 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyLoggerInjectionTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyLoggerInjectionTests.cs
@@ -19,13 +19,24 @@ public sealed class AbLegacyLoggerInjectionTests
{
public readonly List<(LogLevel Level, string Message)> Entries = new();
- ///
+ /// Begins a logical operation scope (returns a no-op scope).
+ /// The type of the state to associate with the scope.
+ /// The state identifier for the scope.
+ /// A no-op disposable scope.
public IDisposable BeginScope(TState state) where TState : notnull => NullScope.Instance;
- ///
+ /// Checks whether logging is enabled for the given level (always true).
+ /// The log level to check.
+ /// always.
public bool IsEnabled(LogLevel logLevel) => true;
- ///
+ /// Records a log entry into the captured entries list.
+ /// The type of the log state object.
+ /// The severity level of the log entry.
+ /// The event identifier for the log entry.
+ /// The state object associated with the log entry.
+ /// An optional exception to log.
+ /// A function that formats the state and exception into a message string.
public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception,
Func formatter)
=> Entries.Add((logLevel, formatter(state, exception)));
@@ -33,7 +44,7 @@ public sealed class AbLegacyLoggerInjectionTests
{
public static readonly NullScope Instance = new();
- ///
+ /// Disposes the no-op scope (no-op).
public void Dispose() { }
}
}
@@ -50,6 +61,7 @@ public sealed class AbLegacyLoggerInjectionTests
}
/// Verifies that driver initialization failure emits an error log.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task InitializeAsync_failure_emits_error_log()
{
@@ -68,6 +80,7 @@ public sealed class AbLegacyLoggerInjectionTests
}
/// Verifies that the first non-zero libplctag status per device is logged.
+ /// A task that represents the asynchronous test operation.
[Fact]
public async Task First_nonzero_libplctag_status_per_device_is_logged()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyReadWriteTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyReadWriteTests.cs
index 97b4c627..89670e74 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyReadWriteTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyReadWriteTests.cs
@@ -23,6 +23,7 @@ public sealed class AbLegacyReadWriteTests
// ---- Read ----
/// Verifies that an unknown reference maps to BadNodeIdUnknown.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Unknown_reference_maps_to_BadNodeIdUnknown()
{
@@ -34,6 +35,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that a successful N-file read returns a Good status.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Successful_N_file_read_returns_Good_value()
{
@@ -51,6 +53,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that repeated reads reuse the runtime.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Repeat_read_reuses_runtime()
{
@@ -67,6 +70,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that non-zero libplctag status values map via AbLegacyStatusMapper.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task NonZero_libplctag_status_maps_via_AbLegacyStatusMapper()
{
@@ -82,6 +86,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that read exceptions surface as BadCommunicationError.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Read_exception_surfaces_BadCommunicationError()
{
@@ -96,6 +101,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that batched reads preserve order.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Batched_reads_preserve_order()
{
@@ -120,6 +126,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that read tag creation parameters are composed from device and profile.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Read_TagCreateParams_composed_from_device_and_profile()
{
@@ -140,6 +147,7 @@ public sealed class AbLegacyReadWriteTests
// ---- Write ----
/// Verifies that a non-writable tag rejects with BadNotWritable.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Non_writable_tag_rejects_with_BadNotWritable()
{
@@ -153,6 +161,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that a successful N-file write encodes and flushes the data.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Successful_N_file_write_encodes_and_flushes()
{
@@ -169,6 +178,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that bit-within-word write now succeeds via RMW.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Bit_within_word_write_now_succeeds_via_RMW()
{
@@ -190,6 +200,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that write exceptions surface as BadCommunicationError.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Write_exception_surfaces_BadCommunicationError()
{
@@ -204,6 +215,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that batch write preserves order across different outcomes.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Batch_write_preserves_order_across_outcomes()
{
@@ -233,6 +245,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that cancellation propagates through the driver.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Cancellation_propagates()
{
@@ -250,6 +263,7 @@ public sealed class AbLegacyReadWriteTests
}
/// Verifies that ShutdownAsync disposes all runtimes.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task ShutdownAsync_disposes_runtimes()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyRuntimeConcurrencyTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyRuntimeConcurrencyTests.cs
index e48c81d5..0aca1ef9 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyRuntimeConcurrencyTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/AbLegacyRuntimeConcurrencyTests.cs
@@ -30,9 +30,7 @@ public sealed class AbLegacyRuntimeConcurrencyTests
/// The tag creation parameters.
public OverlapDetectingFake(AbLegacyTagCreateParams p) : base(p) { }
- /// Reads the tag asynchronously while tracking concurrent operations.
- /// The cancellation token.
- /// A task representing the read operation.
+ ///
public override async Task ReadAsync(CancellationToken ct)
{
EnterOp();
@@ -45,9 +43,7 @@ public sealed class AbLegacyRuntimeConcurrencyTests
finally { LeaveOp(); }
}
- /// Writes to the tag asynchronously while tracking concurrent operations.
- /// The cancellation token.
- /// A task representing the write operation.
+ ///
public override async Task WriteAsync(CancellationToken ct)
{
EnterOp();
@@ -69,6 +65,7 @@ public sealed class AbLegacyRuntimeConcurrencyTests
}
/// Verifies that concurrent reads of the same tag are serialised against the shared runtime.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Concurrent_reads_of_same_tag_are_serialised_against_the_shared_runtime()
{
@@ -102,6 +99,7 @@ public sealed class AbLegacyRuntimeConcurrencyTests
}
/// Verifies that concurrent read and write operations on the same tag do not overlap.
+ /// A task that represents the asynchronous operation.
[Fact]
public async Task Concurrent_read_and_write_of_same_tag_do_not_overlap()
{
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/FakeAbLegacyTag.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/FakeAbLegacyTag.cs
index 42528da7..cd3dd8a7 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/FakeAbLegacyTag.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests/FakeAbLegacyTag.cs
@@ -41,9 +41,7 @@ internal class FakeAbLegacyTag : IAbLegacyTagRuntime
/// The tag creation parameters.
public FakeAbLegacyTag(AbLegacyTagCreateParams p) => CreationParams = p;
- /// Initializes the tag asynchronously.
- /// The cancellation token.
- /// A task representing the asynchronous operation.
+ ///
public virtual Task InitializeAsync(CancellationToken ct)
{
InitializeCount++;
@@ -51,9 +49,7 @@ internal class FakeAbLegacyTag : IAbLegacyTagRuntime
return Task.CompletedTask;
}
- /// Reads the tag value asynchronously.
- /// The cancellation token.
- /// A task representing the asynchronous operation.
+ ///
public virtual Task ReadAsync(CancellationToken ct)
{
ReadCount++;
@@ -61,9 +57,7 @@ internal class FakeAbLegacyTag : IAbLegacyTagRuntime
return Task.CompletedTask;
}
- /// Writes the tag value asynchronously.
- /// The cancellation token.
- /// A task representing the asynchronous operation.
+ ///
public virtual Task WriteAsync(CancellationToken ct)
{
WriteCount++;
@@ -71,20 +65,13 @@ internal class FakeAbLegacyTag : IAbLegacyTagRuntime
return Task.CompletedTask;
}
- /// Gets the current tag status.
- /// The status code.
+ ///
public virtual int GetStatus() => Status;
- /// Decodes the tag value based on the specified data type and bit index.
- /// The AbLegacy data type.
- /// The bit index if applicable.
- /// The decoded value.
+ ///
public virtual object? DecodeValue(AbLegacyDataType type, int? bitIndex) => Value;
- /// Encodes the tag value based on the specified data type and bit index.
- /// The AbLegacy data type.
- /// The bit index if applicable.
- /// The value to encode.
+ ///
public virtual void EncodeValue(AbLegacyDataType type, int? bitIndex, object? value) => Value = value;
/// Disposes the tag.
@@ -100,9 +87,7 @@ internal sealed class FakeAbLegacyTagFactory : IAbLegacyTagFactory
/// Gets or sets an optional customization function for tag creation.
public Func? Customise { get; set; }
- /// Creates a new AbLegacy tag with the specified parameters.
- /// The tag creation parameters.
- /// The created tag.
+ ///
public IAbLegacyTagRuntime Create(AbLegacyTagCreateParams p)
{
var fake = Customise?.Invoke(p) ?? new FakeAbLegacyTag(p);
diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/FocasSimFixture.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/FocasSimFixture.cs
index d53875b0..99a6e614 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/FocasSimFixture.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.IntegrationTests/FocasSimFixture.cs
@@ -74,6 +74,7 @@ public sealed class FocasSimFixture : IAsyncDisposable
}
/// Disposes the fixture and releases any held resources.
+ /// A task that represents the asynchronous operation.
public ValueTask DisposeAsync() => ValueTask.CompletedTask;
// ---- Admin API helpers ----
@@ -85,23 +86,27 @@ public sealed class FocasSimFixture : IAsyncDisposable
///
/// The DLL-stem name or OtOpcUa-style alias of the profile to load.
/// Cancellation token for the operation.
+ /// A task that resolves to the JSON response from the admin endpoint.
public Task LoadProfileAsync(string profileName, CancellationToken ct = default) =>
SendAdminAsync("mock_load_profile", new { profile = profileName }, ct);
///