89 lines
4.5 KiB
C#
89 lines
4.5 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Protocol;
|
|
using ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Adapters;
|
|
using ZB.MOM.WW.Secrets.Abstractions;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer;
|
|
|
|
/// <summary>
|
|
/// Default factory that resolves protocol type strings to IDataConnection adapters.
|
|
/// Protocol extensibility: register new adapters via the constructor or AddAdapter method.
|
|
/// </summary>
|
|
public class DataConnectionFactory : IDataConnectionFactory
|
|
{
|
|
private readonly Dictionary<string, Func<IDictionary<string, string>, IDataConnection>> _factories = new(StringComparer.OrdinalIgnoreCase);
|
|
private readonly ILoggerFactory _loggerFactory;
|
|
private readonly ISecretResolver? _secretResolver;
|
|
|
|
/// <summary>
|
|
/// Initializes a new <see cref="DataConnectionFactory"/> with default OPC UA global options.
|
|
/// </summary>
|
|
/// <param name="loggerFactory">Logger factory used when creating protocol adapters.</param>
|
|
public DataConnectionFactory(ILoggerFactory loggerFactory)
|
|
: this(loggerFactory, Options.Create(new OpcUaGlobalOptions())) { }
|
|
|
|
/// <summary>
|
|
/// Initializes a new <see cref="DataConnectionFactory"/> with explicit OPC UA global options.
|
|
/// </summary>
|
|
/// <param name="loggerFactory">Logger factory used when creating protocol adapters.</param>
|
|
/// <param name="opcUaGlobalOptions">Global OPC UA options applied to all OPC UA connections created by this factory.</param>
|
|
/// <param name="secretResolver">
|
|
/// Optional secret resolver threaded into the MxGateway adapter so a per-endpoint
|
|
/// <c>secret:<name></c> ApiKey reference is resolved at connect time. DI supplies it on
|
|
/// the Site container (where <see cref="ISecretResolver"/> is registered); direct
|
|
/// construction without it keeps literal-key behaviour.
|
|
/// </param>
|
|
public DataConnectionFactory(
|
|
ILoggerFactory loggerFactory,
|
|
IOptions<OpcUaGlobalOptions> opcUaGlobalOptions,
|
|
ISecretResolver? secretResolver = null,
|
|
IOptions<DataConnectionOptions>? dataConnectionOptions = null)
|
|
{
|
|
_loggerFactory = loggerFactory;
|
|
_secretResolver = secretResolver;
|
|
var globalOptions = opcUaGlobalOptions.Value;
|
|
// Only the MxGateway supervisory-advise window is adapter-level today; the rest of
|
|
// DataConnectionOptions is consumed by the actor, which is constructed elsewhere.
|
|
var supervisoryAdviseParallelism =
|
|
(dataConnectionOptions?.Value ?? new DataConnectionOptions()).MxSupervisoryAdviseParallelism;
|
|
|
|
// Register built-in protocols.
|
|
// Pass the ILoggerFactory into RealOpcUaClientFactory so
|
|
// the RealOpcUaClient it builds gets a real logger — without it the
|
|
// auto-accept-certificate security warning is silently discarded by NullLogger.
|
|
RegisterAdapter("OpcUa", details => new OpcUaDataConnection(
|
|
new RealOpcUaClientFactory(globalOptions, _loggerFactory),
|
|
_loggerFactory.CreateLogger<OpcUaDataConnection>()));
|
|
|
|
// MxGateway: gRPC to the MxAccess Gateway. The RealMxGatewayClient wraps the
|
|
// ZB.MOM.WW.MxGateway.Client package; per-connection config arrives via the
|
|
// flat details dict (see MxGatewayEndpointConfigSerializer).
|
|
RegisterAdapter("MxGateway", details => new MxGatewayDataConnection(
|
|
new RealMxGatewayClientFactory(_loggerFactory),
|
|
_loggerFactory.CreateLogger<MxGatewayDataConnection>(),
|
|
_secretResolver,
|
|
supervisoryAdviseParallelism));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Registers a new protocol adapter factory. This is the extension point
|
|
/// for adding new protocols without modifying existing code.
|
|
/// </summary>
|
|
/// <param name="protocolType">The case-insensitive protocol type string (e.g. "OpcUa").</param>
|
|
/// <param name="factory">Factory delegate that creates an <see cref="IDataConnection"/> from connection details.</param>
|
|
public void RegisterAdapter(string protocolType, Func<IDictionary<string, string>, IDataConnection> factory)
|
|
{
|
|
_factories[protocolType] = factory;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public IDataConnection Create(string protocolType, IDictionary<string, string> connectionDetails)
|
|
{
|
|
if (!_factories.TryGetValue(protocolType, out var factory))
|
|
throw new ArgumentException($"Unknown protocol type: {protocolType}. Registered protocols: {string.Join(", ", _factories.Keys)}");
|
|
|
|
return factory(connectionDetails);
|
|
}
|
|
}
|