feat(driver-ablegacy): shared TagConfigJson readers, writable key, Inspect warnings (R2-11)

This commit is contained in:
Joseph Doherty
2026-07-13 10:59:27 -04:00
parent d374ba332b
commit 6e2415bb4c
4 changed files with 90 additions and 7 deletions
@@ -1,4 +1,5 @@
using System.Text.Json;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.Driver.AbLegacy;
@@ -38,7 +39,7 @@ public static class AbLegacyEquipmentTagParser
return false;
var address = addr.GetString();
if (string.IsNullOrWhiteSpace(address)) return false;
var dataType = ReadEnum(root, "dataType", AbLegacyDataType.Int);
var dataType = TagConfigJson.ReadEnumOrDefault(root, "dataType", AbLegacyDataType.Int);
var deviceHostAddress = ReadString(root, "deviceHostAddress");
int? arrayLength = null;
if (IsArrayFlag(root))
@@ -47,9 +48,12 @@ public static class AbLegacyEquipmentTagParser
if (rawLength >= 1)
arrayLength = Math.Min(rawLength, AbLegacyArray.MaxElements);
}
// "writable" defaults to true when absent (today's value) — makes read-only equipment tags
// authorable (UNDER-6).
var writable = TagConfigJson.ReadWritable(root);
def = new AbLegacyTagDefinition(
Name: reference, DeviceHostAddress: deviceHostAddress, Address: address,
DataType: dataType, Writable: true, ArrayLength: arrayLength);
DataType: dataType, Writable: writable, ArrayLength: arrayLength);
return true;
}
catch (JsonException) { return false; }
@@ -57,9 +61,35 @@ public static class AbLegacyEquipmentTagParser
catch (InvalidOperationException) { return false; }
}
private static TEnum ReadEnum<TEnum>(JsonElement o, string name, TEnum fallback) where TEnum : struct, Enum
=> o.TryGetProperty(name, out var e) && e.ValueKind == JsonValueKind.String
&& Enum.TryParse<TEnum>(e.GetString(), ignoreCase: true, out var v) ? v : fallback;
/// <summary>
/// Deploy-time inspection (05/CONV-2): warns on a present-but-invalid <c>dataType</c> (silently
/// defaulted by the lenient runtime) and on a structurally unparseable TagConfig. Empty when clean
/// or not an equipment-tag object. Never throws.
/// </summary>
/// <param name="reference">The equipment tag's TagConfig JSON.</param>
/// <returns>The warnings; empty when clean.</returns>
public static IReadOnlyList<string> Inspect(string reference)
{
var warnings = new List<string>();
if (string.IsNullOrWhiteSpace(reference) || reference[0] != '{') return warnings;
try
{
using var doc = JsonDocument.Parse(reference);
var root = doc.RootElement;
if (root.ValueKind != JsonValueKind.Object)
{
warnings.Add("AbLegacy TagConfig root is not a JSON object — the tag will not resolve (BadNodeIdUnknown).");
return warnings;
}
var w = TagConfigJson.DescribeInvalidEnum<AbLegacyDataType>(root, "dataType");
if (w is not null) warnings.Add(w);
}
catch (JsonException)
{
warnings.Add("AbLegacy TagConfig is not valid JSON — the tag will not resolve (BadNodeIdUnknown).");
}
return warnings;
}
private static string ReadString(JsonElement o, string name)
=> o.TryGetProperty(name, out var e) && e.ValueKind == JsonValueKind.String
@@ -5,5 +5,9 @@
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<!-- NO PackageReference. -->
<!-- NO PackageReference. ProjectReference only to the zero-dependency Core.Abstractions leaf
(R2-11 05/CONV-2 — shared TagConfigJson readers). -->
<ItemGroup>
<ProjectReference Include="..\..\Core\ZB.MOM.WW.OtOpcUa.Core.Abstractions\ZB.MOM.WW.OtOpcUa.Core.Abstractions.csproj"/>
</ItemGroup>
</Project>