refactor: rename ScadaLink → ZB.MOM.WW.ScadaBridge (code + projects + namespaces)
Solution + 23 src projects + 26 test projects renamed; folders, csproj, namespaces, and ScadaLinkDbContext/ScadaBridgeDbContext class updated. ActorSystem "scadalink" → "scadabridge", Akka seed-node URLs migrated. SQL roles/logins, LDAP domains, CLI command name, and CLI config dir (~/.scadalink → ~/.scadabridge) also renamed. Build green; 5 Host.Tests fail awaiting SQL login rename in next commit. Pre-existing StaleTagMonitor timing flakes unchanged. Rename script committed at tools/rename-to-scadabridge.sh.
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Adapters;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration options for OPC UA connections, parsed from connection details JSON.
|
||||
/// All values have defaults matching the OPC Foundation SDK's typical settings.
|
||||
/// </summary>
|
||||
public record OpcUaConnectionOptions(
|
||||
int SessionTimeoutMs = 60000,
|
||||
int OperationTimeoutMs = 15000,
|
||||
int PublishingIntervalMs = 1000,
|
||||
int KeepAliveCount = 10,
|
||||
int LifetimeCount = 30,
|
||||
int MaxNotificationsPerPublish = 100,
|
||||
int SamplingIntervalMs = 1000,
|
||||
int QueueSize = 10,
|
||||
string SecurityMode = "None",
|
||||
// DataConnectionLayer-012: secure-by-default — untrusted server certificates are
|
||||
// rejected unless an operator explicitly opts in per connection. Accepting any
|
||||
// certificate defeats the Sign / SignAndEncrypt modes against a man-in-the-middle.
|
||||
bool AutoAcceptUntrustedCerts = false,
|
||||
bool DiscardOldest = true,
|
||||
byte SubscriptionPriority = 0,
|
||||
string SubscriptionDisplayName = "ScadaBridge",
|
||||
string TimestampsToReturn = "Source",
|
||||
OpcUaDeadbandOptions? Deadband = null,
|
||||
OpcUaUserIdentityOptions? UserIdentity = null);
|
||||
|
||||
public record OpcUaDeadbandOptions(string Type, double Value);
|
||||
|
||||
public record OpcUaUserIdentityOptions(
|
||||
string TokenType,
|
||||
string Username,
|
||||
string Password,
|
||||
string CertificatePath,
|
||||
string CertificatePassword);
|
||||
|
||||
/// <summary>
|
||||
/// WP-7: Abstraction over OPC UA client library for testability.
|
||||
/// The real implementation would wrap an OPC UA SDK (e.g., OPC Foundation .NET Standard Library).
|
||||
/// </summary>
|
||||
public interface IOpcUaClient : IAsyncDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Connects to an OPC UA server at the specified endpoint URL.
|
||||
/// </summary>
|
||||
/// <param name="endpointUrl">The OPC UA server endpoint URL.</param>
|
||||
/// <param name="options">Connection options; if null, defaults are used.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task ConnectAsync(string endpointUrl, OpcUaConnectionOptions? options = null, CancellationToken cancellationToken = default);
|
||||
/// <summary>
|
||||
/// Disconnects from the OPC UA server.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task DisconnectAsync(CancellationToken cancellationToken = default);
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the client is currently connected to the server.
|
||||
/// </summary>
|
||||
bool IsConnected { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a monitored item subscription for a node. Returns a subscription handle.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The OPC UA node ID to monitor.</param>
|
||||
/// <param name="onValueChanged">Callback invoked when the monitored value changes, receiving nodeId, value, sourceTimestamp, and statusCode.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
|
||||
/// <returns>A task that completes with a subscription handle string.</returns>
|
||||
Task<string> CreateSubscriptionAsync(
|
||||
string nodeId,
|
||||
Action<string, object?, DateTime, uint> onValueChanged,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Removes a monitored item subscription by handle.
|
||||
/// </summary>
|
||||
/// <param name="subscriptionHandle">The subscription handle returned by CreateSubscriptionAsync.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task RemoveSubscriptionAsync(string subscriptionHandle, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the current value of a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The OPC UA node ID to read.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
|
||||
/// <returns>A task that completes with a tuple of (value, sourceTimestamp, statusCode).</returns>
|
||||
Task<(object? Value, DateTime SourceTimestamp, uint StatusCode)> ReadValueAsync(
|
||||
string nodeId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Writes a value to a node.
|
||||
/// </summary>
|
||||
/// <param name="nodeId">The OPC UA node ID to write to.</param>
|
||||
/// <param name="value">The value to write.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
|
||||
/// <returns>A task that completes with the OPC UA status code of the write operation.</returns>
|
||||
Task<uint> WriteValueAsync(string nodeId, object? value, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the OPC UA session detects a keep-alive failure or the server
|
||||
/// becomes unreachable. The adapter layer uses this to trigger reconnection.
|
||||
/// </summary>
|
||||
event Action? ConnectionLost;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory for creating IOpcUaClient instances.
|
||||
/// </summary>
|
||||
public interface IOpcUaClientFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new IOpcUaClient instance.
|
||||
/// </summary>
|
||||
/// <returns>A new IOpcUaClient instance.</returns>
|
||||
IOpcUaClient Create();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default factory that creates stub OPC UA clients.
|
||||
/// In production, this would create real OPC UA SDK client instances.
|
||||
/// </summary>
|
||||
public class DefaultOpcUaClientFactory : IOpcUaClientFactory
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public IOpcUaClient Create() => new StubOpcUaClient();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stub OPC UA client for development/testing. A real implementation would
|
||||
/// wrap the OPC Foundation .NET Standard Library.
|
||||
/// </summary>
|
||||
internal class StubOpcUaClient : IOpcUaClient
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public bool IsConnected { get; private set; }
|
||||
#pragma warning disable CS0067
|
||||
/// <inheritdoc />
|
||||
public event Action? ConnectionLost;
|
||||
#pragma warning restore CS0067
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ConnectAsync(string endpointUrl, OpcUaConnectionOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
IsConnected = true;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task DisconnectAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
IsConnected = false;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<string> CreateSubscriptionAsync(
|
||||
string nodeId, Action<string, object?, DateTime, uint> onValueChanged,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult(Guid.NewGuid().ToString());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task RemoveSubscriptionAsync(string subscriptionHandle, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<(object? Value, DateTime SourceTimestamp, uint StatusCode)> ReadValueAsync(
|
||||
string nodeId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult<(object?, DateTime, uint)>((null, DateTime.UtcNow, 0));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<uint> WriteValueAsync(string nodeId, object? value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.FromResult<uint>(0); // Good status
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
IsConnected = false;
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user