feat(alarms): EquipmentTagPlan.Alarm parsed byte-parity from TagConfig (Phase B WS-2)

This commit is contained in:
Joseph Doherty
2026-06-14 03:12:48 -04:00
parent f44d8d1e6b
commit e1ccd99ea2
7 changed files with 98 additions and 14 deletions
@@ -445,7 +445,8 @@ public static class DeploymentArtifact
Name: name!,
DataType: dataType ?? "BaseDataType",
FullName: ExtractTagFullName(tagConfig),
Writable: writable));
Writable: writable,
Alarm: ExtractTagAlarm(tagConfig)));
}
result.Sort((a, b) =>
@@ -651,6 +652,26 @@ public static class DeploymentArtifact
return tagConfig;
}
/// <summary>Parses the optional <c>alarm</c> object from a tag's <c>TagConfig</c> JSON. Returns null
/// when absent, non-object, or non-JSON (the tag is then a plain variable). Never throws. The
/// live-edit side (<c>Phase7Composer.ExtractTagAlarm</c>) MUST parse identically (byte-parity).</summary>
private static EquipmentTagAlarmInfo? ExtractTagAlarm(string? tagConfig)
{
if (string.IsNullOrWhiteSpace(tagConfig)) return null;
try
{
using var doc = JsonDocument.Parse(tagConfig);
if (doc.RootElement.ValueKind != JsonValueKind.Object) return null;
if (!doc.RootElement.TryGetProperty("alarm", out var a) || a.ValueKind != JsonValueKind.Object) return null;
var type = a.TryGetProperty("alarmType", out var tEl) && tEl.ValueKind == JsonValueKind.String
? (tEl.GetString() ?? "AlarmCondition") : "AlarmCondition";
var sev = a.TryGetProperty("severity", out var sEl) && sEl.ValueKind == JsonValueKind.Number
? sEl.GetInt32() : 500;
return new EquipmentTagAlarmInfo(type, sev);
}
catch (JsonException) { return null; }
}
private static IReadOnlyList<T> ReadArray<T>(JsonElement root, string propertyName, Func<JsonElement, T?> reader)
where T : class
{