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]