85 lines
3.5 KiB
C#
85 lines
3.5 KiB
C#
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
|
using ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.PlcFamilies;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.AbLegacy;
|
|
|
|
/// <summary>
|
|
/// AB Legacy / PCCC driver — SLC 500, MicroLogix, PLC-5, LogixPccc. Implements
|
|
/// <see cref="IDriver"/> only at PR 1 time; read / write / discovery / subscribe / probe /
|
|
/// host-resolver capabilities ship in PRs 2 and 3.
|
|
/// </summary>
|
|
public sealed class AbLegacyDriver : IDriver, IDisposable, IAsyncDisposable
|
|
{
|
|
private readonly AbLegacyDriverOptions _options;
|
|
private readonly string _driverInstanceId;
|
|
private readonly Dictionary<string, DeviceState> _devices = new(StringComparer.OrdinalIgnoreCase);
|
|
private DriverHealth _health = new(DriverState.Unknown, null, null);
|
|
|
|
public AbLegacyDriver(AbLegacyDriverOptions options, string driverInstanceId)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(options);
|
|
_options = options;
|
|
_driverInstanceId = driverInstanceId;
|
|
}
|
|
|
|
public string DriverInstanceId => _driverInstanceId;
|
|
public string DriverType => "AbLegacy";
|
|
|
|
public Task InitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
|
|
{
|
|
_health = new DriverHealth(DriverState.Initializing, null, null);
|
|
try
|
|
{
|
|
foreach (var device in _options.Devices)
|
|
{
|
|
var addr = AbLegacyHostAddress.TryParse(device.HostAddress)
|
|
?? throw new InvalidOperationException(
|
|
$"AbLegacy device has invalid HostAddress '{device.HostAddress}' — expected 'ab://gateway[:port]/cip-path'.");
|
|
var profile = AbLegacyPlcFamilyProfile.ForFamily(device.PlcFamily);
|
|
_devices[device.HostAddress] = new DeviceState(addr, device, profile);
|
|
}
|
|
_health = new DriverHealth(DriverState.Healthy, DateTime.UtcNow, null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_health = new DriverHealth(DriverState.Faulted, null, ex.Message);
|
|
throw;
|
|
}
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public async Task ReinitializeAsync(string driverConfigJson, CancellationToken cancellationToken)
|
|
{
|
|
await ShutdownAsync(cancellationToken).ConfigureAwait(false);
|
|
await InitializeAsync(driverConfigJson, cancellationToken).ConfigureAwait(false);
|
|
}
|
|
|
|
public Task ShutdownAsync(CancellationToken cancellationToken)
|
|
{
|
|
_devices.Clear();
|
|
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public DriverHealth GetHealth() => _health;
|
|
public long GetMemoryFootprint() => 0;
|
|
public Task FlushOptionalCachesAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
|
|
|
internal int DeviceCount => _devices.Count;
|
|
internal DeviceState? GetDeviceState(string hostAddress) =>
|
|
_devices.TryGetValue(hostAddress, out var s) ? s : null;
|
|
|
|
public void Dispose() => DisposeAsync().AsTask().GetAwaiter().GetResult();
|
|
public async ValueTask DisposeAsync() => await ShutdownAsync(CancellationToken.None).ConfigureAwait(false);
|
|
|
|
internal sealed class DeviceState(
|
|
AbLegacyHostAddress parsedAddress,
|
|
AbLegacyDeviceOptions options,
|
|
AbLegacyPlcFamilyProfile profile)
|
|
{
|
|
public AbLegacyHostAddress ParsedAddress { get; } = parsedAddress;
|
|
public AbLegacyDeviceOptions Options { get; } = options;
|
|
public AbLegacyPlcFamilyProfile Profile { get; } = profile;
|
|
}
|
|
}
|