feat(historian-gateway): AlarmHistorianEvent->HistorianEvent mapper (SendEvent properties)
Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
using Google.Protobuf.WellKnownTypes;
|
||||||
|
using ZB.MOM.WW.HistorianGateway.Contracts.Grpc;
|
||||||
|
using ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian;
|
||||||
|
|
||||||
|
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Mapping;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps a driver-agnostic <see cref="AlarmHistorianEvent"/> onto a gateway wire
|
||||||
|
/// <see cref="HistorianEvent"/> for the <c>SendEvent</c> write path.
|
||||||
|
/// </summary>
|
||||||
|
internal static class AlarmEventMapper
|
||||||
|
{
|
||||||
|
/// <summary>Maps an alarm historian event to a gateway event.</summary>
|
||||||
|
/// <param name="alarm">The driver-agnostic alarm event.</param>
|
||||||
|
/// <returns>The gateway wire event ready for <c>SendEvent</c>.</returns>
|
||||||
|
public static HistorianEvent ToHistorianEvent(AlarmHistorianEvent alarm)
|
||||||
|
{
|
||||||
|
// Timestamp.FromDateTime requires a Utc-kind DateTime; coerce defensively (TimestampUtc is
|
||||||
|
// already Utc by contract, but a caller could pass Unspecified).
|
||||||
|
var eventTime = Timestamp.FromDateTime(DateTime.SpecifyKind(alarm.TimestampUtc, DateTimeKind.Utc));
|
||||||
|
|
||||||
|
var historianEvent = new HistorianEvent
|
||||||
|
{
|
||||||
|
Id = string.IsNullOrWhiteSpace(alarm.AlarmId) ? Guid.NewGuid().ToString("N") : alarm.AlarmId,
|
||||||
|
SourceName = alarm.EquipmentPath,
|
||||||
|
Type = alarm.AlarmTypeName,
|
||||||
|
EventTime = eventTime,
|
||||||
|
ReceivedTime = eventTime, // the server re-stamps the received time on the SQL path
|
||||||
|
};
|
||||||
|
|
||||||
|
// Proto map<string,string> values must be non-null — only insert non-null properties.
|
||||||
|
historianEvent.Properties["AlarmName"] = alarm.AlarmName;
|
||||||
|
historianEvent.Properties["EventKind"] = alarm.EventKind;
|
||||||
|
historianEvent.Properties["Severity"] = alarm.Severity.ToString();
|
||||||
|
historianEvent.Properties["User"] = alarm.User;
|
||||||
|
historianEvent.Properties["Message"] = alarm.Message;
|
||||||
|
if (alarm.Comment is not null)
|
||||||
|
historianEvent.Properties["Comment"] = alarm.Comment;
|
||||||
|
|
||||||
|
return historianEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
using Xunit;
|
||||||
|
using ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian; // AlarmHistorianEvent
|
||||||
|
using ZB.MOM.WW.OtOpcUa.Core.Abstractions; // AlarmSeverity
|
||||||
|
using ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Mapping;
|
||||||
|
|
||||||
|
namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests.Mapping;
|
||||||
|
|
||||||
|
public sealed class AlarmEventMapperTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Maps_source_time_type_and_rich_properties()
|
||||||
|
{
|
||||||
|
var a = new AlarmHistorianEvent("A1", "Area/Line/Pump1", "HiHi", "LimitAlarm",
|
||||||
|
AlarmSeverity.High, "Activated", "Temp high", "operator1", "ack note",
|
||||||
|
new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
var e = AlarmEventMapper.ToHistorianEvent(a);
|
||||||
|
Assert.Equal("Area/Line/Pump1", e.SourceName);
|
||||||
|
Assert.Equal("LimitAlarm", e.Type);
|
||||||
|
Assert.Equal(new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc), e.EventTime.ToDateTime());
|
||||||
|
Assert.Equal("HiHi", e.Properties["AlarmName"]);
|
||||||
|
Assert.Equal("Activated", e.Properties["EventKind"]);
|
||||||
|
Assert.Equal("High", e.Properties["Severity"]);
|
||||||
|
Assert.Equal("operator1", e.Properties["User"]);
|
||||||
|
Assert.Equal("ack note", e.Properties["Comment"]);
|
||||||
|
Assert.Equal("Temp high", e.Properties["Message"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Null_comment_is_omitted_not_null()
|
||||||
|
{
|
||||||
|
var a = new AlarmHistorianEvent("A", "S", "N", "DiscreteAlarm", AlarmSeverity.Low, "Cleared", "m", "system", null,
|
||||||
|
new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc));
|
||||||
|
Assert.False(AlarmEventMapper.ToHistorianEvent(a).Properties.ContainsKey("Comment"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user