diff --git a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayAlarmMapper.cs b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayAlarmMapper.cs index e3a7b7c5..c91d6765 100644 --- a/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayAlarmMapper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/Adapters/MxGatewayAlarmMapper.cs @@ -86,7 +86,14 @@ public static class MxGatewayAlarmMapper /// The gateway alarm transition event proto message to map. /// The protocol-neutral . public static NativeAlarmTransition MapTransition(OnAlarmTransitionEvent body) => new( - SourceReference: body.AlarmFullReference, + // Identify the condition by the object-relative reference (e.g. + // "Z28061.HeartbeatTimeoutAlarm") rather than the gateway's full provider + // reference ("Galaxy!.."). The area is preserved in + // Category; the object reference is globally unique within the galaxy and + // is the form operators expect. Falls back to the full reference only if + // the gateway omits the object reference. + SourceReference: string.IsNullOrEmpty(body.SourceObjectReference) + ? body.AlarmFullReference : body.SourceObjectReference, SourceObjectReference: body.SourceObjectReference, AlarmTypeName: body.AlarmTypeName, Kind: MapKind(body.TransitionKind), @@ -112,7 +119,10 @@ public static class MxGatewayAlarmMapper /// The active alarm snapshot proto message to map. /// A with AlarmTransitionKind.Snapshot. public static NativeAlarmTransition MapSnapshot(ActiveAlarmSnapshot snapshot) => new( - SourceReference: snapshot.AlarmFullReference, + // See MapTransition: identify by the object-relative reference, not the + // full "Galaxy!.." provider reference. + SourceReference: string.IsNullOrEmpty(snapshot.SourceObjectReference) + ? snapshot.AlarmFullReference : snapshot.SourceObjectReference, SourceObjectReference: snapshot.SourceObjectReference, AlarmTypeName: snapshot.AlarmTypeName, Kind: AlarmTransitionKind.Snapshot, diff --git a/tests/ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests/MxGatewayAlarmMapperTests.cs b/tests/ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests/MxGatewayAlarmMapperTests.cs index 5f8eaf3e..438ffbdc 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests/MxGatewayAlarmMapperTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Tests/MxGatewayAlarmMapperTests.cs @@ -65,6 +65,54 @@ public class MxGatewayAlarmMapperTests Assert.Equal(1000, t.Condition.Severity); } + [Fact] + public void SourceReference_IsObjectRelative_NotFullProviderReference() + { + // The condition identity surfaced upward is the object-relative reference + // (e.g. "Z28061.HeartbeatTimeoutAlarm"), not the gateway's full provider + // reference ("Galaxy!.."). Area lives in Category. + var snap = new ActiveAlarmSnapshot + { + AlarmFullReference = "Galaxy!CVDAisle_1.Z28061.HeartbeatTimeoutAlarm", + SourceObjectReference = "Z28061.HeartbeatTimeoutAlarm", + AlarmTypeName = "Syst", + Category = "CVDAisle_1", + CurrentState = ProtoConditionState.Active, + Severity = 400 + }; + var ev = new OnAlarmTransitionEvent + { + AlarmFullReference = "Galaxy!CVDAisle_1.Z28061.HeartbeatTimeoutAlarm", + SourceObjectReference = "Z28061.HeartbeatTimeoutAlarm", + AlarmTypeName = "Syst", + TransitionKind = ProtoTransitionKind.Raise, + Severity = 400 + }; + + var snapT = MxGatewayAlarmMapper.MapSnapshot(snap); + var liveT = MxGatewayAlarmMapper.MapTransition(ev); + + Assert.Equal("Z28061.HeartbeatTimeoutAlarm", snapT.SourceReference); + Assert.Equal("Z28061.HeartbeatTimeoutAlarm", liveT.SourceReference); + Assert.Equal("CVDAisle_1", snapT.Category); + } + + [Fact] + public void SourceReference_FallsBackToFullReference_WhenObjectReferenceEmpty() + { + var snap = new ActiveAlarmSnapshot + { + AlarmFullReference = "Galaxy!Area.Obj.Alarm", + SourceObjectReference = "", + CurrentState = ProtoConditionState.Active, + Severity = 100 + }; + + var t = MxGatewayAlarmMapper.MapSnapshot(snap); + + Assert.Equal("Galaxy!Area.Obj.Alarm", t.SourceReference); + } + // ── CurrentValue / LimitValue (M2.13 / #27) ────────────────────────────── [Fact]