using System.Globalization; using ZB.MOM.WW.HistorianGateway.Contracts.Grpc; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Mapping; /// /// Maps a gateway wire event () onto the driver-agnostic /// consumed by the Server's HistoryReadEvents path. /// internal static class EventMapper { /// OPC UA severity range (Part 9): 1 (lowest) … 1000 (highest). private const ushort MinSeverity = 1; private const ushort MaxSeverity = 1000; /// Maps a single gateway event to a historical event. /// The gateway wire event. /// The driver-agnostic historical event. public static HistoricalEvent ToHistoricalEvent(HistorianEvent historianEvent) { // Message: prefer the "Message" property, else fall back to the event Type (best-effort // render); never null-crash on a missing property. string? message; if (historianEvent.Properties.TryGetValue("Message", out var m) && !string.IsNullOrEmpty(m)) message = m; else message = string.IsNullOrEmpty(historianEvent.Type) ? null : historianEvent.Type; return new HistoricalEvent( EventId: historianEvent.Id, SourceName: string.IsNullOrEmpty(historianEvent.SourceName) ? null : historianEvent.SourceName, EventTimeUtc: historianEvent.EventTime?.ToDateTime() ?? default, // Utc kind ReceivedTimeUtc: historianEvent.ReceivedTime?.ToDateTime() ?? default, // Utc kind Message: message, Severity: ParseSeverity(historianEvent.Properties)); } /// Maps a batch of gateway events to historical events, in order. /// The gateway wire events. /// The driver-agnostic historical events. public static IReadOnlyList ToHistoricalEvents(IEnumerable events) { var result = new List(); foreach (var historianEvent in events) result.Add(ToHistoricalEvent(historianEvent)); return result; } /// /// Parses an OPC UA severity from the "Severity" property (else "Priority"), clamped to /// [1, 1000]. Missing or unparseable values default to the minimum severity (1). /// private static ushort ParseSeverity(IDictionary properties) { string? raw = null; if (properties.TryGetValue("Severity", out var severity)) raw = severity; else if (properties.TryGetValue("Priority", out var priority)) raw = priority; if (int.TryParse(raw, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) return (ushort)Math.Clamp(value, MinSeverity, MaxSeverity); return MinSeverity; } }