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
@@ -241,6 +241,8 @@ public sealed class DeploymentArtifactAliasParityTests
};
// The Galaxy equipment tag — FullName is the Galaxy ref "tag_name.AttributeName".
// It also carries a native-alarm intent in TagConfig.alarm, so this draft proves the
// optional Alarm field is parsed byte-identically on both producers (Phase B WS-2).
var galaxyTag = new Tag
{
TagId = "tag-galaxy",
@@ -250,7 +252,7 @@ public sealed class DeploymentArtifactAliasParityTests
Name = "DownloadPath",
DataType = "String",
AccessLevel = TagAccessLevel.Read,
TagConfig = "{\"FullName\":\"DelmiaReceiver_001.DownloadPath\"}",
TagConfig = "{\"FullName\":\"DelmiaReceiver_001.DownloadPath\",\"alarm\":{\"alarmType\":\"OffNormalAlarm\",\"severity\":700}}",
};
// A non-Galaxy (Modbus) equipment tag — proves the parity holds across drivers, not just Galaxy.
var modbusTag = new Tag
@@ -315,6 +317,7 @@ public sealed class DeploymentArtifactAliasParityTests
d.DataType.ShouldBe(x.DataType);
d.FullName.ShouldBe(x.FullName);
d.Writable.ShouldBe(x.Writable);
d.Alarm.ShouldBe(x.Alarm); // EquipmentTagAlarmInfo is a positional record ⇒ value equality
}
var galaxyPlan = decoded.EquipmentTags.Single(t => t.TagId == "tag-galaxy");
@@ -323,6 +326,15 @@ public sealed class DeploymentArtifactAliasParityTests
galaxyPlan.DriverInstanceId.ShouldBe("drv-galaxy");
galaxyPlan.FolderPath.ShouldBe(string.Empty); // null FolderPath coalesced identically on both sides
// The native-alarm intent in the Galaxy tag's TagConfig.alarm is parsed byte-identically on both
// producers (Phase B WS-2). The Modbus tag has no alarm object ⇒ null Alarm on both sides.
galaxyPlan.Alarm.ShouldNotBeNull();
galaxyPlan.Alarm!.AlarmType.ShouldBe("OffNormalAlarm");
galaxyPlan.Alarm.Severity.ShouldBe(700);
composed.EquipmentTags.Single(t => t.TagId == "tag-galaxy").Alarm.ShouldBe(galaxyPlan.Alarm);
decoded.EquipmentTags.Single(t => t.TagId == "tag-modbus").Alarm.ShouldBeNull();
composed.EquipmentTags.Single(t => t.TagId == "tag-modbus").Alarm.ShouldBeNull();
// Writability flows from Tag.AccessLevel: the Galaxy tag is Read (read-only node), the Modbus
// tag is ReadWrite (writable node). Both producers must derive the same Writable flag, and the
// SequenceEqual above already proves they agree element-wise.