using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
using ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Config;
namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy;
///
/// In-process .NET 10 Galaxy driver — the v2 replacement for the Galaxy.Host /
/// Galaxy.Proxy pair. PR 4.0 ships the project skeleton with
/// bodies that wire to a future IGalaxyGatewayClient abstraction. Capability
/// interfaces (browse, read, write, subscribe, history routing, host probes) land in
/// PRs 4.1–4.7; the wiring sequence keeps every intermediate state buildable so the
/// Galaxy:Backend flag (PR 4.W) can flip between legacy-host and mxgateway
/// for parity testing.
///
///
/// This driver is registered as a Tier A in-process driver alongside Modbus / S7 / etc.
/// The legacy GalaxyProxyDriver (Driver.Galaxy.Proxy) coexists until PR 7.2;
/// registers under driver-type name
/// "GalaxyMxGateway" so both paths can be live simultaneously during parity testing.
///
public sealed class GalaxyDriver : IDriver, IDisposable
{
private readonly string _driverInstanceId;
private readonly GalaxyDriverOptions _options;
private readonly ILogger _logger;
private DriverHealth _health = new(DriverState.Unknown, null, null);
private bool _disposed;
public GalaxyDriver(
string driverInstanceId,
GalaxyDriverOptions options,
ILogger? logger = null)
{
_driverInstanceId = !string.IsNullOrWhiteSpace(driverInstanceId)
? driverInstanceId
: throw new ArgumentException("Driver instance id required.", nameof(driverInstanceId));
_options = options ?? throw new ArgumentNullException(nameof(options));
_logger = logger ?? NullLogger.Instance;
}
///
public string DriverInstanceId => _driverInstanceId;
///
public string DriverType => GalaxyDriverFactoryExtensions.DriverTypeName;
/// Test-visible options snapshot.
internal GalaxyDriverOptions Options => _options;
///
public Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
ObjectDisposedException.ThrowIf(_disposed, this);
// PR 4.0 skeleton — capability bodies (PRs 4.1-4.7) replace this stub with real
// MxGatewayClient session opening. The skeleton keeps the IDriver shape buildable
// so the Galaxy:Backend flag (PR 4.W) can register the driver factory now.
_logger.LogInformation(
"GalaxyDriver {InstanceId} initializing — endpoint={Endpoint} clientName={ClientName} (skeleton; real gateway connect in PR 4.1+)",
_driverInstanceId, _options.Gateway.Endpoint, _options.MxAccess.ClientName);
_health = new DriverHealth(DriverState.Healthy, DateTime.UtcNow, null);
return Task.CompletedTask;
}
///
public Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
{
// In-place config reapply. PR 4.5's reconnect supervisor will swap the
// gateway-client options under the lock; for the skeleton we just refresh health.
ObjectDisposedException.ThrowIf(_disposed, this);
_health = new DriverHealth(DriverState.Healthy, DateTime.UtcNow, null);
return Task.CompletedTask;
}
///
public Task ShutdownAsync(CancellationToken cancellationToken)
{
if (_disposed) return Task.CompletedTask;
_logger.LogInformation("GalaxyDriver {InstanceId} shutting down", _driverInstanceId);
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
return Task.CompletedTask;
}
///
public DriverHealth GetHealth() => _health;
///
public long GetMemoryFootprint() => 0; // PR 4.4 sets this from SubscriptionRegistry size.
///
public Task FlushOptionalCachesAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public void Dispose()
{
if (_disposed) return;
_disposed = true;
// No owned IDisposables until PR 4.2's GalaxyMxSession lands.
}
}