feat(twincat): resolve equipment-tag refs (read + write) via EquipmentTagRefResolver

This commit is contained in:
Joseph Doherty
2026-06-13 11:24:12 -04:00
parent e2ea720c08
commit 5ebf541f54
3 changed files with 144 additions and 3 deletions
@@ -27,6 +27,12 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
new(StringComparer.OrdinalIgnoreCase);
private readonly ConcurrentDictionary<string, TwinCATTagDefinition> _tagsByName =
new(StringComparer.OrdinalIgnoreCase);
// Resolves a read/write/subscribe fullReference to a tag definition, bridging the two
// authoring models: an authored tag-table entry (by name) OR an equipment tag whose
// reference is its raw TagConfig JSON (parsed once via TwinCATEquipmentTagParser, cached).
private readonly EquipmentTagRefResolver<TwinCATTagDefinition> _resolver;
private DriverHealth _health = new(DriverState.Unknown, null, null);
/// <summary>Occurs when a subscribed tag value changes.</summary>
@@ -50,6 +56,9 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
_driverInstanceId = driverInstanceId;
_clientFactory = clientFactory ?? new AdsTwinCATClientFactory();
_logger = logger ?? NullLogger<TwinCATDriver>.Instance;
_resolver = new EquipmentTagRefResolver<TwinCATTagDefinition>(
r => _tagsByName.TryGetValue(r, out var t) ? t : null,
r => TwinCATEquipmentTagParser.TryParse(r, out var d) ? d : null);
_poll = new PollGroupEngine(
reader: ReadAsync,
onChange: (handle, tagRef, snapshot) =>
@@ -151,6 +160,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
}
_devices.Clear();
_tagsByName.Clear();
_resolver.Clear(); // drop transient equipment-tag parses so a config change re-parses
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
}
@@ -201,7 +211,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
for (var i = 0; i < fullReferences.Count; i++)
{
var reference = fullReferences[i];
if (!_tagsByName.TryGetValue(reference, out var def))
if (!_resolver.TryResolve(reference, out var def))
{
results[i] = new DataValueSnapshot(null, TwinCATStatusMapper.BadNodeIdUnknown, null, now);
continue;
@@ -258,7 +268,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
for (var i = 0; i < writes.Count; i++)
{
var w = writes[i];
if (!_tagsByName.TryGetValue(w.FullReference, out var def))
if (!_resolver.TryResolve(w.FullReference, out var def))
{
results[i] = new WriteResult(TwinCATStatusMapper.BadNodeIdUnknown);
continue;
@@ -412,7 +422,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
{
foreach (var reference in fullReferences)
{
if (!_tagsByName.TryGetValue(reference, out var def)) continue;
if (!_resolver.TryResolve(reference, out var def)) continue;
if (!_devices.TryGetValue(def.DeviceHostAddress, out var device)) continue;
var client = await EnsureConnectedAsync(device, cancellationToken).ConfigureAwait(false);
@@ -655,6 +665,7 @@ public sealed class TwinCATDriver : IDriver, IReadable, IWritable, ITagDiscovery
}
_devices.Clear();
_tagsByName.Clear();
_resolver.Clear(); // drop transient equipment-tag parses so a config change re-parses
_health = new DriverHealth(DriverState.Unknown, _health.LastSuccessfulRead, null);
}