Auto: abcip-3.1 — configurable CIP connection size per device
Closes #235
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Reflection;
|
||||
using libplctag;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip;
|
||||
@@ -12,6 +13,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip;
|
||||
internal sealed class LibplctagTagRuntime : IAbCipTagRuntime
|
||||
{
|
||||
private readonly Tag _tag;
|
||||
private readonly int _connectionSize;
|
||||
|
||||
public LibplctagTagRuntime(AbCipTagCreateParams p)
|
||||
{
|
||||
@@ -35,12 +37,55 @@ internal sealed class LibplctagTagRuntime : IAbCipTagRuntime
|
||||
// to issue one Rockwell array read for a [N..M] slice.
|
||||
if (p.ElementCount is int n && n > 0)
|
||||
_tag.ElementCount = n;
|
||||
_connectionSize = p.ConnectionSize;
|
||||
}
|
||||
|
||||
public async Task InitializeAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await _tag.InitializeAsync(cancellationToken).ConfigureAwait(false);
|
||||
// PR abcip-3.1 — propagate the configured CIP connection size to the native libplctag
|
||||
// handle. The 1.5.x C# wrapper does not expose <c>connection_size</c> as a public Tag
|
||||
// property, so we reach into the internal <c>NativeTagWrapper</c>'s
|
||||
// <c>SetIntAttribute</c> (mirroring libplctag's <c>plc_tag_set_int_attribute</c>).
|
||||
// libplctag native parses <c>connection_size</c> at create time, so this best-effort
|
||||
// call lights up automatically when a future wrapper release exposes the attribute or
|
||||
// when libplctag native gains post-create hot-update support — until then it falls back
|
||||
// to the wrapper default. Failures (older / patched wrappers without the internal API)
|
||||
// are intentionally swallowed so the driver keeps initialising.
|
||||
TrySetConnectionSize(_tag, _connectionSize);
|
||||
}
|
||||
|
||||
public Task InitializeAsync(CancellationToken cancellationToken) => _tag.InitializeAsync(cancellationToken);
|
||||
public Task ReadAsync(CancellationToken cancellationToken) => _tag.ReadAsync(cancellationToken);
|
||||
public Task WriteAsync(CancellationToken cancellationToken) => _tag.WriteAsync(cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Best-effort propagation of <c>connection_size</c> to libplctag native. Reflects into
|
||||
/// the wrapper's internal <c>NativeTagWrapper.SetIntAttribute(string, int)</c>; isolated
|
||||
/// in a static helper so the lookup costs run once + the failure path is one line.
|
||||
/// </summary>
|
||||
private static void TrySetConnectionSize(Tag tag, int connectionSize)
|
||||
{
|
||||
try
|
||||
{
|
||||
var wrapperField = typeof(Tag).GetField("_tag", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var wrapper = wrapperField?.GetValue(tag);
|
||||
if (wrapper is null) return;
|
||||
var setInt = wrapper.GetType().GetMethod(
|
||||
"SetIntAttribute",
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
|
||||
binder: null,
|
||||
types: [typeof(string), typeof(int)],
|
||||
modifiers: null);
|
||||
setInt?.Invoke(wrapper, ["connection_size", connectionSize]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Wrapper internals shifted (newer libplctag.NET) — drop quietly. Either the new
|
||||
// wrapper exposes ConnectionSize directly (our reflection no-ops) or operators must
|
||||
// upgrade to a known-good version per docs/drivers/AbCip-Performance.md.
|
||||
}
|
||||
}
|
||||
|
||||
public int GetStatus() => (int)_tag.GetStatus();
|
||||
|
||||
public object? DecodeValue(AbCipDataType type, int? bitIndex) => DecodeValueAt(type, 0, bitIndex);
|
||||
|
||||
Reference in New Issue
Block a user