feat(twincat): 1-D array symbol read via ADS + IsArray discovery
This commit is contained in:
@@ -70,13 +70,19 @@ public sealed record TwinCATDeviceOptions(
|
||||
/// One TwinCAT-backed OPC UA variable. <paramref name="SymbolPath"/> is the full TwinCAT
|
||||
/// symbolic name (e.g. <c>MAIN.bStart</c>, <c>GVL.Counter</c>, <c>Motor1.Status.Running</c>).
|
||||
/// </summary>
|
||||
/// <param name="ArrayLength">
|
||||
/// When non-null, this tag is a 1-D array of <paramref name="ArrayLength"/> elements of
|
||||
/// <paramref name="DataType"/>. Drives <c>IsArray</c>/<c>ArrayDim</c> at discovery and a
|
||||
/// native ADS array read at runtime (Phase 4c). <c>null</c> = scalar (the default).
|
||||
/// </param>
|
||||
public sealed record TwinCATTagDefinition(
|
||||
string Name,
|
||||
string DeviceHostAddress,
|
||||
string SymbolPath,
|
||||
TwinCATDataType DataType,
|
||||
bool Writable = true,
|
||||
bool WriteIdempotent = false);
|
||||
bool WriteIdempotent = false,
|
||||
int? ArrayLength = null);
|
||||
|
||||
/// <summary>Probe options for TwinCAT connection monitoring.</summary>
|
||||
public sealed class TwinCATProbeOptions
|
||||
|
||||
+20
-1
@@ -29,9 +29,14 @@ public static class TwinCATEquipmentTagParser
|
||||
if (string.IsNullOrWhiteSpace(symbolPath)) return false;
|
||||
var deviceHostAddress = ReadString(root, "deviceHostAddress");
|
||||
var dataType = ReadEnum(root, "dataType", TwinCATDataType.DInt);
|
||||
// Array intent — same shape the runtime/OPC-UA foundation parses (camelCase
|
||||
// `isArray` bool + `arrayLength` uint). arrayLength is honoured ONLY when isArray
|
||||
// is true AND it is a positive JSON number, so a stale length behind a cleared
|
||||
// isArray never produces an orphan array tag (Phase 4c).
|
||||
var arrayLength = ReadArrayLength(root);
|
||||
def = new TwinCATTagDefinition(
|
||||
Name: reference, DeviceHostAddress: deviceHostAddress, SymbolPath: symbolPath,
|
||||
DataType: dataType, Writable: true);
|
||||
DataType: dataType, Writable: true, ArrayLength: arrayLength);
|
||||
return true;
|
||||
}
|
||||
catch (JsonException) { return false; }
|
||||
@@ -46,4 +51,18 @@ public static class TwinCATEquipmentTagParser
|
||||
private static string ReadString(JsonElement o, string name)
|
||||
=> o.TryGetProperty(name, out var e) && e.ValueKind == JsonValueKind.String
|
||||
? e.GetString() ?? "" : "";
|
||||
|
||||
/// <summary>
|
||||
/// Reads the optional 1-D array length: <c>arrayLength</c> (a positive uint) honoured ONLY
|
||||
/// when <c>isArray</c> is the JSON literal <c>true</c>. Returns <c>null</c> (scalar) when
|
||||
/// isArray is absent/false, when arrayLength is absent / non-numeric / zero / negative.
|
||||
/// </summary>
|
||||
private static int? ReadArrayLength(JsonElement o)
|
||||
{
|
||||
if (!o.TryGetProperty("isArray", out var aEl) || aEl.ValueKind != JsonValueKind.True)
|
||||
return null;
|
||||
if (!o.TryGetProperty("arrayLength", out var lEl) || lEl.ValueKind != JsonValueKind.Number)
|
||||
return null;
|
||||
return lEl.TryGetInt32(out var len) && len > 0 ? len : null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user