68 lines
3.3 KiB
C#
68 lines
3.3 KiB
C#
using Google.Protobuf.WellKnownTypes;
|
|
using ZB.MOM.WW.HistorianGateway.Contracts.Grpc;
|
|
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
|
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 <see cref="AlarmSeverity"/> to the numeric OPC UA Part 9 priority (1-1000) carried in the
|
|
/// wire event's <c>Severity</c> property, per the <see cref="AlarmHistorianEvent.Severity"/>
|
|
/// contract ("Mapped to Historian's numeric priority on the sink side"). The read side
|
|
/// (<see cref="EventMapper.ToHistoricalEvent"/>) <c>int.TryParse</c>s this same property, so it
|
|
/// must stay a numeric string — the enum's <c>.ToString()</c> name (e.g. "High") is NOT
|
|
/// parseable and used to silently collapse every read-back severity to the minimum (1). The
|
|
/// values mirror the existing native-alarm convention
|
|
/// (<c>ZB.MOM.WW.OtOpcUa.Runtime.Drivers.NativeAlarmProjector.MapSeverity</c>).
|
|
/// </summary>
|
|
private static string ToNumericSeverity(AlarmSeverity severity) => severity switch
|
|
{
|
|
AlarmSeverity.Low => "200",
|
|
AlarmSeverity.Medium => "500",
|
|
AlarmSeverity.High => "700",
|
|
AlarmSeverity.Critical => "900",
|
|
_ => "500",
|
|
};
|
|
|
|
/// <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)
|
|
{
|
|
if (alarm.DeliveryId == Guid.Empty)
|
|
throw new ArgumentException("Alarm delivery identity must be nonzero.", nameof(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
|
|
{
|
|
// Identity belongs to the event/durable queue, never to an individual RPC attempt.
|
|
Id = alarm.DeliveryId.ToString("D"),
|
|
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.
|
|
if (!string.IsNullOrWhiteSpace(alarm.AlarmId))
|
|
historianEvent.Properties["AlarmId"] = alarm.AlarmId;
|
|
historianEvent.Properties["AlarmName"] = alarm.AlarmName;
|
|
historianEvent.Properties["EventKind"] = alarm.EventKind;
|
|
historianEvent.Properties["Severity"] = ToNumericSeverity(alarm.Severity);
|
|
historianEvent.Properties["User"] = alarm.User;
|
|
historianEvent.Properties["Message"] = alarm.Message;
|
|
if (alarm.Comment is not null)
|
|
historianEvent.Properties["Comment"] = alarm.Comment;
|
|
|
|
return historianEvent;
|
|
}
|
|
}
|