Document client stack XML docs progress
This commit is contained in:
@@ -12,20 +12,40 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
private static readonly ILogger Logger = Log.ForContext<DefaultSessionAdapter>();
|
||||
private readonly Session _session;
|
||||
|
||||
/// <summary>
|
||||
/// Wraps a live OPC UA session so the shared client can issue runtime operations through a testable adapter surface.
|
||||
/// </summary>
|
||||
/// <param name="session">The connected OPC UA session used for browsing, reads, writes, history, and subscriptions.</param>
|
||||
public DefaultSessionAdapter(Session session)
|
||||
{
|
||||
_session = session;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Connected => _session.Connected;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string SessionId => _session.SessionId?.ToString() ?? string.Empty;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string SessionName => _session.SessionName ?? string.Empty;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string EndpointUrl => _session.Endpoint?.EndpointUrl ?? string.Empty;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string ServerName => _session.Endpoint?.Server?.ApplicationName?.Text ?? string.Empty;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string SecurityMode => _session.Endpoint?.SecurityMode.ToString() ?? string.Empty;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string SecurityPolicyUri => _session.Endpoint?.SecurityPolicyUri ?? string.Empty;
|
||||
|
||||
/// <inheritdoc />
|
||||
public NamespaceTable NamespaceUris => _session.NamespaceUris;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RegisterKeepAliveHandler(Action<bool> callback)
|
||||
{
|
||||
_session.KeepAlive += (_, e) =>
|
||||
@@ -35,11 +55,13 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DataValue> ReadValueAsync(NodeId nodeId, CancellationToken ct)
|
||||
{
|
||||
return await _session.ReadValueAsync(nodeId, ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<StatusCode> WriteValueAsync(NodeId nodeId, DataValue value, CancellationToken ct)
|
||||
{
|
||||
var writeValue = new WriteValue
|
||||
@@ -54,6 +76,7 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
return response.Results[0];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<(byte[]? ContinuationPoint, ReferenceDescriptionCollection References)> BrowseAsync(
|
||||
NodeId nodeId, uint nodeClassMask, CancellationToken ct)
|
||||
{
|
||||
@@ -70,6 +93,7 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
return (continuationPoint, references ?? []);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<(byte[]? ContinuationPoint, ReferenceDescriptionCollection References)> BrowseNextAsync(
|
||||
byte[] continuationPoint, CancellationToken ct)
|
||||
{
|
||||
@@ -77,6 +101,7 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
return (nextCp, nextRefs ?? []);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> HasChildrenAsync(NodeId nodeId, CancellationToken ct)
|
||||
{
|
||||
var (_, _, references) = await _session.BrowseAsync(
|
||||
@@ -92,6 +117,7 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
return references != null && references.Count > 0;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<DataValue>> HistoryReadRawAsync(
|
||||
NodeId nodeId, DateTime startTime, DateTime endTime, int maxValues, CancellationToken ct)
|
||||
{
|
||||
@@ -142,6 +168,7 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
return allValues;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<DataValue>> HistoryReadAggregateAsync(
|
||||
NodeId nodeId, DateTime startTime, DateTime endTime, NodeId aggregateId, double intervalMs,
|
||||
CancellationToken ct)
|
||||
@@ -182,6 +209,7 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
return allValues;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<ISubscriptionAdapter> CreateSubscriptionAsync(int publishingIntervalMs, CancellationToken ct)
|
||||
{
|
||||
var subscription = new Subscription(_session.DefaultSubscription)
|
||||
@@ -196,6 +224,7 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
return new DefaultSubscriptionAdapter(subscription);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task CloseAsync(CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -208,6 +237,9 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the wrapped OPC UA session when the shared client shuts down or swaps endpoints during failover.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
@@ -221,6 +253,7 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
_session.Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IList<object>?> CallMethodAsync(NodeId objectId, NodeId methodId, object[] inputArguments,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
@@ -243,4 +276,4 @@ internal sealed class DefaultSessionAdapter : ISessionAdapter
|
||||
|
||||
return callResult.OutputArguments?.Select(v => v.Value).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,19 @@ internal sealed class DefaultSubscriptionAdapter : ISubscriptionAdapter
|
||||
private readonly Dictionary<uint, MonitoredItem> _monitoredItems = new();
|
||||
private readonly Subscription _subscription;
|
||||
|
||||
/// <summary>
|
||||
/// Wraps a live OPC UA subscription so client code can manage monitored items through a testable abstraction.
|
||||
/// </summary>
|
||||
/// <param name="subscription">The underlying OPC UA subscription that owns monitored items for this client workflow.</param>
|
||||
public DefaultSubscriptionAdapter(Subscription subscription)
|
||||
{
|
||||
_subscription = subscription;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public uint SubscriptionId => _subscription.Id;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<uint> AddDataChangeMonitoredItemAsync(
|
||||
NodeId nodeId, int samplingIntervalMs, Action<string, DataValue> onDataChange, CancellationToken ct)
|
||||
{
|
||||
@@ -46,6 +52,7 @@ internal sealed class DefaultSubscriptionAdapter : ISubscriptionAdapter
|
||||
return handle;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task RemoveMonitoredItemAsync(uint clientHandle, CancellationToken ct)
|
||||
{
|
||||
if (!_monitoredItems.TryGetValue(clientHandle, out var item))
|
||||
@@ -58,6 +65,7 @@ internal sealed class DefaultSubscriptionAdapter : ISubscriptionAdapter
|
||||
Logger.Debug("Removed monitored item handle={Handle}", clientHandle);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<uint> AddEventMonitoredItemAsync(
|
||||
NodeId nodeId, int samplingIntervalMs, EventFilter filter, Action<EventFieldList> onEvent, CancellationToken ct)
|
||||
{
|
||||
@@ -86,11 +94,13 @@ internal sealed class DefaultSubscriptionAdapter : ISubscriptionAdapter
|
||||
return handle;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task ConditionRefreshAsync(CancellationToken ct)
|
||||
{
|
||||
await _subscription.ConditionRefreshAsync(ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task DeleteAsync(CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -105,6 +115,9 @@ internal sealed class DefaultSubscriptionAdapter : ISubscriptionAdapter
|
||||
_monitoredItems.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the wrapped OPC UA subscription and clears tracked monitored items held by the adapter.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
@@ -117,4 +130,4 @@ internal sealed class DefaultSubscriptionAdapter : ISubscriptionAdapter
|
||||
|
||||
_monitoredItems.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,59 +7,134 @@ namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters;
|
||||
/// </summary>
|
||||
internal interface ISessionAdapter : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the underlying OPC UA session is currently usable for client operations.
|
||||
/// </summary>
|
||||
bool Connected { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the server-assigned session identifier for diagnostics and failover reporting.
|
||||
/// </summary>
|
||||
string SessionId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the friendly session name presented to the OPC UA server.
|
||||
/// </summary>
|
||||
string SessionName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the active endpoint URL that this adapter is connected to.
|
||||
/// </summary>
|
||||
string EndpointUrl { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the server name reported by the connected OPC UA endpoint.
|
||||
/// </summary>
|
||||
string ServerName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the negotiated OPC UA message security mode for the session.
|
||||
/// </summary>
|
||||
string SecurityMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the negotiated OPC UA security policy URI for the session.
|
||||
/// </summary>
|
||||
string SecurityPolicyUri { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the namespace table used to resolve expanded node identifiers returned by browse operations.
|
||||
/// </summary>
|
||||
NamespaceTable NamespaceUris { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Registers a keep-alive callback. The callback receives true when the session is healthy, false on failure.
|
||||
/// </summary>
|
||||
/// <param name="callback">The callback used by higher-level clients to trigger reconnect or failover behavior.</param>
|
||||
void RegisterKeepAliveHandler(Action<bool> callback);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the current value for a node from the connected OPC UA server.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node whose current runtime value should be read.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the server read if the client cancels the request.</param>
|
||||
Task<DataValue> ReadValueAsync(NodeId nodeId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a typed value to a node on the connected OPC UA server.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node whose value should be updated.</param>
|
||||
/// <param name="value">The typed OPC UA data value to write to the server.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the write if the client cancels the request.</param>
|
||||
Task<StatusCode> WriteValueAsync(NodeId nodeId, DataValue value, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Browses forward hierarchical references from the given node.
|
||||
/// Returns (continuationPoint, references).
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The starting node for the hierarchical browse.</param>
|
||||
/// <param name="nodeClassMask">The node classes that should be returned to the caller.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the browse request.</param>
|
||||
Task<(byte[]? ContinuationPoint, ReferenceDescriptionCollection References)> BrowseAsync(
|
||||
NodeId nodeId, uint nodeClassMask = 0, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Continues a browse from a continuation point.
|
||||
/// </summary>
|
||||
/// <param name="continuationPoint">The continuation token returned by a prior browse result page.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the browse-next request.</param>
|
||||
Task<(byte[]? ContinuationPoint, ReferenceDescriptionCollection References)> BrowseNextAsync(
|
||||
byte[] continuationPoint, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a node has any forward hierarchical child references.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node to inspect for child objects or variables.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the child lookup.</param>
|
||||
Task<bool> HasChildrenAsync(NodeId nodeId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reads raw historical data.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The historized node whose raw samples should be retrieved.</param>
|
||||
/// <param name="startTime">The inclusive start of the requested history window.</param>
|
||||
/// <param name="endTime">The inclusive end of the requested history window.</param>
|
||||
/// <param name="maxValues">The maximum number of raw samples to return to the client.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the history read.</param>
|
||||
Task<IReadOnlyList<DataValue>> HistoryReadRawAsync(NodeId nodeId, DateTime startTime, DateTime endTime,
|
||||
int maxValues, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reads processed/aggregate historical data.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The historized node whose processed values should be retrieved.</param>
|
||||
/// <param name="startTime">The inclusive start of the requested processed-history window.</param>
|
||||
/// <param name="endTime">The inclusive end of the requested processed-history window.</param>
|
||||
/// <param name="aggregateId">The OPC UA aggregate function to evaluate over the history window.</param>
|
||||
/// <param name="intervalMs">The processing interval, in milliseconds, for each aggregate bucket.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the aggregate history read.</param>
|
||||
Task<IReadOnlyList<DataValue>> HistoryReadAggregateAsync(NodeId nodeId, DateTime startTime, DateTime endTime,
|
||||
NodeId aggregateId, double intervalMs, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a subscription adapter for this session.
|
||||
/// </summary>
|
||||
/// <param name="publishingIntervalMs">The requested publishing interval for monitored items on the new subscription.</param>
|
||||
/// <param name="ct">The cancellation token that aborts subscription creation.</param>
|
||||
Task<ISubscriptionAdapter> CreateSubscriptionAsync(int publishingIntervalMs, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Calls an OPC UA method node with the provided input arguments.
|
||||
/// </summary>
|
||||
/// <param name="objectId">The object node that owns the target method.</param>
|
||||
/// <param name="methodId">The method node to invoke.</param>
|
||||
/// <param name="inputArguments">The ordered input arguments supplied to the server method call.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the method invocation.</param>
|
||||
Task<IList<object>?> CallMethodAsync(NodeId objectId, NodeId methodId, object[] inputArguments, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Closes the underlying session gracefully before the adapter is disposed or replaced during failover.
|
||||
/// </summary>
|
||||
/// <param name="ct">The cancellation token that aborts the close request.</param>
|
||||
Task CloseAsync(CancellationToken ct = default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ namespace ZB.MOM.WW.LmxOpcUa.Client.Shared.Adapters;
|
||||
/// </summary>
|
||||
internal interface ISubscriptionAdapter : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the server-assigned subscription identifier for diagnostics and reconnect workflows.
|
||||
/// </summary>
|
||||
uint SubscriptionId { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -23,6 +26,8 @@ internal interface ISubscriptionAdapter : IDisposable
|
||||
/// <summary>
|
||||
/// Removes a previously added monitored item by its client handle.
|
||||
/// </summary>
|
||||
/// <param name="clientHandle">The client handle returned when the monitored item was created.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the monitored-item removal.</param>
|
||||
Task RemoveMonitoredItemAsync(uint clientHandle, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
@@ -40,10 +45,12 @@ internal interface ISubscriptionAdapter : IDisposable
|
||||
/// <summary>
|
||||
/// Requests a condition refresh for this subscription.
|
||||
/// </summary>
|
||||
/// <param name="ct">The cancellation token that aborts the condition refresh request.</param>
|
||||
Task ConditionRefreshAsync(CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Removes all monitored items and deletes the subscription.
|
||||
/// </summary>
|
||||
/// <param name="ct">The cancellation token that aborts subscription deletion.</param>
|
||||
Task DeleteAsync(CancellationToken ct = default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,33 +9,136 @@ namespace ZB.MOM.WW.LmxOpcUa.Client.Shared;
|
||||
/// </summary>
|
||||
public interface IOpcUaClientService : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the client is currently connected to an OPC UA endpoint.
|
||||
/// </summary>
|
||||
bool IsConnected { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current connection metadata shown to CLI and UI operators after a successful connect or failover.
|
||||
/// </summary>
|
||||
ConnectionInfo? CurrentConnectionInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Connects the client to the configured OPC UA endpoint set, including failover-capable endpoints when provided.
|
||||
/// </summary>
|
||||
/// <param name="settings">The endpoint, security, and authentication settings used to establish the session.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the connect workflow.</param>
|
||||
Task<ConnectionInfo> ConnectAsync(ConnectionSettings settings, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects from the active OPC UA endpoint and tears down subscriptions owned by the client.
|
||||
/// </summary>
|
||||
/// <param name="ct">The cancellation token that aborts disconnect cleanup.</param>
|
||||
Task DisconnectAsync(CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the current value of an OPC UA node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node whose value should be retrieved.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the read request.</param>
|
||||
Task<DataValue> ReadValueAsync(NodeId nodeId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Writes an operator-supplied value to an OPC UA node after applying client-side type conversion when needed.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node whose value should be updated.</param>
|
||||
/// <param name="value">The raw value supplied by the CLI or UI workflow.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the write request.</param>
|
||||
Task<StatusCode> WriteValueAsync(NodeId nodeId, object value, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Browses the children of a node so the client can build an address-space tree for operators.
|
||||
/// </summary>
|
||||
/// <param name="parentNodeId">The node to browse, or <see cref="ObjectIds.ObjectsFolder"/> when omitted.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the browse request.</param>
|
||||
Task<IReadOnlyList<BrowseResult>> BrowseAsync(NodeId? parentNodeId = null, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to live data changes for a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node whose value changes should be monitored.</param>
|
||||
/// <param name="intervalMs">The monitored-item sampling and publishing interval in milliseconds.</param>
|
||||
/// <param name="ct">The cancellation token that aborts subscription creation.</param>
|
||||
Task SubscribeAsync(NodeId nodeId, int intervalMs = 1000, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a previously created live-data subscription for a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The node whose live-data subscription should be removed.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the unsubscribe request.</param>
|
||||
Task UnsubscribeAsync(NodeId nodeId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes to OPC UA alarm and condition events for a source node or the server root.
|
||||
/// </summary>
|
||||
/// <param name="sourceNodeId">The event source to monitor, or the server object when omitted.</param>
|
||||
/// <param name="intervalMs">The publishing interval in milliseconds for the alarm subscription.</param>
|
||||
/// <param name="ct">The cancellation token that aborts alarm subscription creation.</param>
|
||||
Task SubscribeAlarmsAsync(NodeId? sourceNodeId = null, int intervalMs = 1000, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the active alarm subscription.
|
||||
/// </summary>
|
||||
/// <param name="ct">The cancellation token that aborts alarm subscription cleanup.</param>
|
||||
Task UnsubscribeAlarmsAsync(CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Requests retained alarm conditions again so a client can repopulate its alarm list after reconnecting.
|
||||
/// </summary>
|
||||
/// <param name="ct">The cancellation token that aborts the condition refresh request.</param>
|
||||
Task RequestConditionRefreshAsync(CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Acknowledges an active condition using the event identifier returned by an alarm notification.
|
||||
/// </summary>
|
||||
/// <param name="conditionNodeId">The condition node associated with the alarm event being acknowledged.</param>
|
||||
/// <param name="eventId">The event identifier returned by the OPC UA server for the alarm event.</param>
|
||||
/// <param name="comment">The operator acknowledgment comment to write with the method call.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the acknowledgment request.</param>
|
||||
Task<StatusCode> AcknowledgeAlarmAsync(string conditionNodeId, byte[] eventId, string comment, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reads raw historical samples for a historized node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The historized node whose samples should be read.</param>
|
||||
/// <param name="startTime">The inclusive start of the requested history range.</param>
|
||||
/// <param name="endTime">The inclusive end of the requested history range.</param>
|
||||
/// <param name="maxValues">The maximum number of raw values to return.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the history read.</param>
|
||||
Task<IReadOnlyList<DataValue>> HistoryReadRawAsync(NodeId nodeId, DateTime startTime, DateTime endTime,
|
||||
int maxValues = 1000, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reads aggregate historical values for a historized node using an OPC UA aggregate function.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The historized node whose processed values should be read.</param>
|
||||
/// <param name="startTime">The inclusive start of the requested processed-history range.</param>
|
||||
/// <param name="endTime">The inclusive end of the requested processed-history range.</param>
|
||||
/// <param name="aggregate">The aggregate function the operator selected for processed history.</param>
|
||||
/// <param name="intervalMs">The processing interval, in milliseconds, for each aggregate bucket.</param>
|
||||
/// <param name="ct">The cancellation token that aborts the processed history request.</param>
|
||||
Task<IReadOnlyList<DataValue>> HistoryReadAggregateAsync(NodeId nodeId, DateTime startTime, DateTime endTime,
|
||||
AggregateType aggregate, double intervalMs = 3600000, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reads redundancy status data such as redundancy mode, service level, and partner endpoint URIs.
|
||||
/// </summary>
|
||||
/// <param name="ct">The cancellation token that aborts redundancy inspection.</param>
|
||||
Task<RedundancyInfo> GetRedundancyInfoAsync(CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a subscribed node produces a new live data value.
|
||||
/// </summary>
|
||||
event EventHandler<DataChangedEventArgs>? DataChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when an alarm or condition event is received from the server.
|
||||
/// </summary>
|
||||
event EventHandler<AlarmEventArgs>? AlarmEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the client changes connection state during connect, disconnect, or failover.
|
||||
/// </summary>
|
||||
event EventHandler<ConnectionStateChangedEventArgs>? ConnectionStateChanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,9 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
/// <summary>
|
||||
/// Creates a new OpcUaClientService with the specified adapter dependencies.
|
||||
/// </summary>
|
||||
/// <param name="configFactory">Builds the application configuration and certificate settings for the client session.</param>
|
||||
/// <param name="endpointDiscovery">Selects the best matching endpoint for the requested URL and security mode.</param>
|
||||
/// <param name="sessionFactory">Creates the underlying OPC UA session used for runtime operations.</param>
|
||||
internal OpcUaClientService(
|
||||
IApplicationConfigurationFactory configFactory,
|
||||
IEndpointDiscovery endpointDiscovery,
|
||||
@@ -59,13 +62,22 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<DataChangedEventArgs>? DataChanged;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<AlarmEventArgs>? AlarmEvent;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<ConnectionStateChangedEventArgs>? ConnectionStateChanged;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsConnected => _state == ConnectionState.Connected && _session?.Connected == true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ConnectionInfo? CurrentConnectionInfo { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<ConnectionInfo> ConnectAsync(ConnectionSettings settings, CancellationToken ct = default)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -99,6 +111,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task DisconnectAsync(CancellationToken ct = default)
|
||||
{
|
||||
if (_state == ConnectionState.Disconnected)
|
||||
@@ -140,6 +153,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DataValue> ReadValueAsync(NodeId nodeId, CancellationToken ct = default)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -147,6 +161,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
return await _session!.ReadValueAsync(nodeId, ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<StatusCode> WriteValueAsync(NodeId nodeId, object value, CancellationToken ct = default)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -164,6 +179,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
return await _session!.WriteValueAsync(nodeId, dataValue, ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<BrowseResult>> BrowseAsync(NodeId? parentNodeId = null,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
@@ -200,6 +216,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SubscribeAsync(NodeId nodeId, int intervalMs = 1000, CancellationToken ct = default)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -218,6 +235,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
Logger.Debug("Subscribed to data changes on {NodeId}", nodeId);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task UnsubscribeAsync(NodeId nodeId, CancellationToken ct = default)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -232,6 +250,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
Logger.Debug("Unsubscribed from data changes on {NodeId}", nodeId);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SubscribeAlarmsAsync(NodeId? sourceNodeId = null, int intervalMs = 1000,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
@@ -252,6 +271,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
Logger.Debug("Subscribed to alarm events on {NodeId}", monitorNode);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task UnsubscribeAlarmsAsync(CancellationToken ct = default)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -265,6 +285,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
Logger.Debug("Unsubscribed from alarm events");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task RequestConditionRefreshAsync(CancellationToken ct = default)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -277,6 +298,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
Logger.Debug("Condition refresh requested");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<StatusCode> AcknowledgeAlarmAsync(string conditionNodeId, byte[] eventId, string comment,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
@@ -299,6 +321,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
return StatusCodes.Good;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<DataValue>> HistoryReadRawAsync(
|
||||
NodeId nodeId, DateTime startTime, DateTime endTime, int maxValues = 1000, CancellationToken ct = default)
|
||||
{
|
||||
@@ -307,6 +330,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
return await _session!.HistoryReadRawAsync(nodeId, startTime, endTime, maxValues, ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<DataValue>> HistoryReadAggregateAsync(
|
||||
NodeId nodeId, DateTime startTime, DateTime endTime, AggregateType aggregate,
|
||||
double intervalMs = 3600000, CancellationToken ct = default)
|
||||
@@ -317,6 +341,7 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
return await _session!.HistoryReadAggregateAsync(nodeId, startTime, endTime, aggregateNodeId, intervalMs, ct);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<RedundancyInfo> GetRedundancyInfoAsync(CancellationToken ct = default)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -357,6 +382,9 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
return new RedundancyInfo(redundancyMode, serviceLevel, serverUris, applicationUri);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the current session and any active monitored-item subscriptions held by the client service.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
@@ -667,4 +695,4 @@ public sealed class OpcUaClientService : IOpcUaClientService
|
||||
if (_state != ConnectionState.Connected || _session == null)
|
||||
throw new InvalidOperationException("Not connected to an OPC UA server.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user