/// <summary> /// Perform event to message Json encoding /// </summary> /// <param name="messages"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeAsJson( IEnumerable <DataSetMessageModel> messages) { var notifications = GetMonitoredItemMessages(messages, MessageEncoding.Json); if (notifications.Count() == 0) { yield break; } var encodingContext = messages.First().ServiceMessageContext; foreach (var networkMessage in notifications) { var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; networkMessage.Encode(encoder); encoder.Close(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.UaLegacyPublisher, MessageSchema = MessageSchemaTypes.MonitoredItemMessageJson }; yield return(encoded); } }
/// <summary> /// Perform json encoding /// </summary> /// <param name="message"></param> /// <returns></returns> public IEnumerable <NetworkMessageModel> EncodeAsJson(DataSetMessageModel message) { foreach (var networkMessage in GetNetworkMessages(message.YieldReturn())) { using (var writer = new StringWriter()) { using (var encoder = new JsonEncoderEx(writer, message.ServiceMessageContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }) { networkMessage.Encode(encoder); } var json = writer.ToString(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(json), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Json, MessageId = message.SequenceNumber.ToString(), MessageSchema = MessageSchemaTypes.NetworkMessageJson }; yield return(encoded); } } }
/// <summary> /// Perform event to message encoding /// </summary> /// <param name="message"></param> /// <returns></returns> public IEnumerable <NetworkMessageModel> Encode(DataSetMessageModel message) { foreach (var notification in message.Notifications) { var value = new MonitoredItemMessage { MessageContentMask = (message.Writer?.MessageSettings? .DataSetMessageContentMask).ToMonitoredItemMessageMask( message.Writer?.DataSetFieldContentMask), ApplicationUri = message.ApplicationUri, EndpointUrl = message.EndpointUrl, ExtensionFields = message.Writer?.DataSet?.ExtensionFields, NodeId = notification.NodeId, Value = notification.Value, DisplayName = notification.DisplayName }; using (var writer = new StringWriter()) { using (var encoder = new JsonEncoderEx(writer, message.ServiceMessageContext) { // TODO: Configure encoding further UseUriEncoding = true }) { value.Encode(encoder); } var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Json, MessageId = message.SequenceNumber.ToString(), MessageSchema = MessageSchemaTypes.MonitoredItemMessageJson }; yield return(encoded); } } }
/// <summary> /// Perform event to message binary encoding /// </summary> /// <param name="messages"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeAsUadp( IEnumerable <DataSetMessageModel> messages) { var notifications = GetMonitoredItemMessages(messages, MessageEncoding.Uadp); if (notifications.Count() == 0) { yield break; } var encodingContext = messages.First().ServiceMessageContext; foreach (var networkMessage in notifications) { var encoder = new BinaryEncoder(encodingContext); encoder.WriteBoolean(null, false); // is not Batch encoder.WriteEncodeable(null, networkMessage); var encoded = new NetworkMessageModel { Body = encoder.CloseAndReturnBuffer(), Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.UaBinary, MessageSchema = MessageSchemaTypes.MonitoredItemMessageBinary }; yield return(encoded); } }
/// <summary> /// Perform event to message encoding /// </summary> /// <param name="message"></param> /// <returns></returns> public IEnumerable <NetworkMessageModel> EncodeAsUadp(DataSetMessageModel message) { foreach (var notification in message.Notifications) { using (var encoder = new BinaryEncoder(message.ServiceMessageContext)) { var value = new MonitoredItemMessage { MessageContentMask = (message.Writer?.MessageSettings? .DataSetMessageContentMask).ToMonitoredItemMessageMask( message.Writer?.DataSetFieldContentMask), ApplicationUri = message.ApplicationUri, SubscriptionId = message.SubscriptionId, EndpointUrl = message.EndpointUrl, ExtensionFields = message.Writer?.DataSet?.ExtensionFields, NodeId = notification.NodeId.ToExpandedNodeId(message.ServiceMessageContext.NamespaceUris), Timestamp = message.TimeStamp ?? DateTime.UtcNow, Value = notification.Value, DisplayName = notification.DisplayName }; value.Encode(encoder); var encoded = new NetworkMessageModel { Body = encoder.CloseAndReturnBuffer(), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.UaBinary, MessageId = message.SequenceNumber.ToString(), MessageSchema = MessageSchemaTypes.MonitoredItemMessageBinary }; yield return(encoded); } } }
public PCNetworkManager(NetworkMessagesEventArgs incomingMsg) { SQLiteCRUD sql = new SQLiteCRUD(ConnectionStringManager.GetConnectionString(ConnectionStringManager.DataBases.PCControllerDB)); NetworkMessageModel netMsg = new NetworkMessageModel(); if (incomingMsg.IncomingMessage is null) { netMsg.IncomingMessage = string.Empty; } else { netMsg.IncomingMessage = incomingMsg.IncomingMessage; } if (incomingMsg.OutgoingMessage is null) { netMsg.IncomingMessage = string.Empty; } else { netMsg.OutgoingMessage = incomingMsg.OutgoingMessage; } if (incomingMsg.RemoteIP is null) { incomingMsg.RemoteIP = string.Empty; } else { netMsg.RemoteIP = incomingMsg.RemoteIP; } if (incomingMsg.IncomingMessage is null) { incomingMsg.Timestamp = string.Empty; } else { netMsg.Timestamp = incomingMsg.Timestamp; } if (incomingMsg.RemotePort is null) { incomingMsg.RemotePort = string.Empty; } else { netMsg.RemotePort = incomingMsg.RemotePort; } netMsg.UDPPort = incomingMsg.UDPPort; this.UDPPortSet?.Invoke(this, incomingMsg.UDPPort); sql.InsertNetMessage(netMsg); }
/// <summary> /// Perform DataSetMessageModel to batch NetworkMessageModel using binary encoding /// </summary> /// <param name="messages"></param> /// <param name="maxEncodedSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeBatchAsUadp( IEnumerable <DataSetMessageModel> messages, int maxEncodedSize) { var notifications = GetMonitoredItemMessages(messages, MessageEncoding.Uadp); if (notifications.Count() == 0) { yield break; } // take the message context of the first element since is the same for all messages var encodingContext = messages.First().ServiceMessageContext; var current = notifications.GetEnumerator(); var processing = current.MoveNext(); var messageSize = 4; // array length size maxEncodedSize -= 2048; // reserve 2k for header var chunk = new Collection <MonitoredItemMessage>(); while (processing) { var notification = current.Current; var messageCompleted = false; if (notification != null) { var helperEncoder = new BinaryEncoder(encodingContext); helperEncoder.WriteEncodeable(null, notification); var notificationSize = helperEncoder.CloseAndReturnBuffer().Length; messageCompleted = maxEncodedSize < (messageSize + notificationSize); if (!messageCompleted) { chunk.Add(notification); processing = current.MoveNext(); messageSize += notificationSize; } } if (!processing || messageCompleted) { var encoder = new BinaryEncoder(encodingContext); encoder.WriteBoolean(null, true); // is Batch encoder.WriteEncodeableArray(null, chunk); chunk.Clear(); messageSize = 4; var encoded = new NetworkMessageModel { Body = encoder.CloseAndReturnBuffer(), Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.UaBinary, MessageSchema = MessageSchemaTypes.MonitoredItemMessageBinary }; yield return(encoded); } } }
/// <summary> /// Perform json encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeAsJson( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.FirstOrDefault(m => m.ServiceMessageContext != null) ?.ServiceMessageContext; var notifications = GetNetworkMessages(messages, MessageEncoding.Json, encodingContext); if (!notifications.Any()) { yield break; } var routingInfo = messages.FirstOrDefault(m => m?.WriterGroup != null)?.WriterGroup.WriterGroupId; foreach (var networkMessage in notifications) { int notificationsPerMessage = networkMessage.Messages.Sum(m => m.Payload.Count); var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; networkMessage.Encode(encoder); encoder.Close(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Json, MessageSchema = MessageSchemaTypes.NetworkMessageJson, RoutingInfo = _enableRoutingInfo ? routingInfo : null, }; if (encoded.Body.Length > maxMessageSize) { // Message too large, drop it. NotificationsDroppedCount += (uint)notificationsPerMessage; _logger.Warning("Message too large, dropped {notificationsPerMessage} values", notificationsPerMessage); continue; } NotificationsProcessedCount += (uint)notificationsPerMessage; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + notificationsPerMessage) / (MessagesProcessedCount + 1); MessagesProcessedCount++; yield return(encoded); } }
/// <summary> /// Perform json encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeAsJson( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.FirstOrDefault(m => m.ServiceMessageContext != null) ?.ServiceMessageContext; var notifications = GetNetworkMessages(messages, MessageEncoding.Json, encodingContext); if (notifications.Count() == 0) { yield break; } foreach (var networkMessage in notifications) { ulong notificationsPerMessage = (ulong)networkMessage.Messages.Sum(m => m.Payload.Count); var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; networkMessage.Encode(encoder); encoder.Close(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Json, MessageSchema = MessageSchemaTypes.NetworkMessageJson }; if (encoded.Body.Length > maxMessageSize) { // this message is too large to be processed. Drop it // TODO Trace NotificationsDroppedCount++; yield break; } NotificationsProcessedCount++; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + notificationsPerMessage) / (MessagesProcessedCount + 1); MessagesProcessedCount++; yield return(encoded); } }
/// <summary> /// Perform uadp encoding /// </summary> /// <param name="message"></param> /// <returns></returns> public IEnumerable <NetworkMessageModel> EncodeAsUadp(DataSetMessageModel message) { foreach (var networkMessage in GetNetworkMessages(message.YieldReturn())) { using (var encoder = new BinaryEncoder(message.ServiceMessageContext)) { networkMessage.Encode(encoder); var encoded = new NetworkMessageModel { Body = encoder.CloseAndReturnBuffer(), Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Uadp, MessageId = message.SequenceNumber.ToString(), MessageSchema = MessageSchemaTypes.NetworkMessageUadp }; yield return(encoded); } } }
/// <summary> /// Perform uadp encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeAsUadp( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.FirstOrDefault(m => m.ServiceMessageContext != null) ?.ServiceMessageContext; var notifications = GetNetworkMessages(messages, MessageEncoding.Uadp, encodingContext); if (!notifications.Any()) { yield break; } var routingInfo = messages.FirstOrDefault(m => m?.WriterGroup != null)?.WriterGroup.WriterGroupId; foreach (var networkMessage in notifications) { int notificationsPerMessage = networkMessage.Messages.Sum(m => m.Payload.Count); var encoder = new BinaryEncoder(encodingContext); encoder.WriteBoolean(null, false); // is not Batch encoder.WriteEncodeable(null, networkMessage); networkMessage.Encode(encoder); var encoded = new NetworkMessageModel { Body = encoder.CloseAndReturnBuffer(), Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Uadp, MessageSchema = MessageSchemaTypes.NetworkMessageUadp, RoutingInfo = _enableRoutingInfo ? routingInfo : null, }; if (encoded.Body.Length > maxMessageSize) { // Message too large, drop it. NotificationsDroppedCount += (uint)notificationsPerMessage; _logger.Warning("Message too large, dropped {notificationsPerMessage} values", notificationsPerMessage); continue; } NotificationsProcessedCount += (uint)notificationsPerMessage; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + notificationsPerMessage) / (MessagesProcessedCount + 1); MessagesProcessedCount++; yield return(encoded); } }
/// <summary> /// Perform uadp encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeAsUadp( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.FirstOrDefault(m => m.ServiceMessageContext != null) ?.ServiceMessageContext; var notifications = GetNetworkMessages(messages, MessageEncoding.Uadp, encodingContext); if (notifications.Count() == 0) { yield break; } foreach (var networkMessage in notifications) { ulong notificationsPerMessage = (ulong)networkMessage.Messages.Sum(m => m.Payload.Count); var encoder = new BinaryEncoder(encodingContext); encoder.WriteBoolean(null, false); // is not Batch encoder.WriteEncodeable(null, networkMessage); networkMessage.Encode(encoder); var encoded = new NetworkMessageModel { Body = encoder.CloseAndReturnBuffer(), Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Uadp, MessageSchema = MessageSchemaTypes.NetworkMessageUadp }; if (encoded.Body.Length > maxMessageSize) { // this message is too large to be processed. Drop it // TODO Trace NotificationsDroppedCount++; yield break; } NotificationsProcessedCount++; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + notificationsPerMessage) / (MessagesProcessedCount + 1); MessagesProcessedCount++; yield return(encoded); } }
/// <summary> /// Perform event to message encoding /// </summary> /// <param name="message"></param> /// <returns></returns> public IEnumerable <NetworkMessageModel> EncodeAsJson(DataSetMessageModel message) { foreach (var notification in message.Notifications) { using (var writer = new StringWriter()) { var value = new MonitoredItemMessage { MessageContentMask = (message.Writer?.MessageSettings? .DataSetMessageContentMask).ToMonitoredItemMessageMask( message.Writer?.DataSetFieldContentMask), ApplicationUri = message.ApplicationUri, EndpointUrl = message.EndpointUrl, ExtensionFields = message.Writer?.DataSet?.ExtensionFields, NodeId = notification.NodeId.ToExpandedNodeId(message.ServiceMessageContext.NamespaceUris), Timestamp = message.TimeStamp ?? DateTime.UtcNow, Value = notification.Value, DisplayName = notification.DisplayName }; using (var encoder = new JsonEncoderEx(writer, message.ServiceMessageContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }){ value.Encode(encoder); } var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.UaLegacyPublisher, MessageId = message.SequenceNumber.ToString(), MessageSchema = MessageSchemaTypes.MonitoredItemMessageJson }; yield return(encoded); } } }
/// <summary> /// DataSetMessage to NetworkMessage Json batched encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeBatchAsJson( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { var notifications = GetNetworkMessages(messages, MessageEncoding.Json); if (notifications.Count() == 0) { yield break; } // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.First().ServiceMessageContext; var current = notifications.GetEnumerator(); var processing = current.MoveNext(); var messageSize = 2; // array brackets maxMessageSize -= 2048; // reserve 2k for header var chunk = new Collection <NetworkMessage>(); while (processing) { var notification = current.Current; var messageCompleted = false; if (notification != null) { var helperWriter = new StringWriter(); var helperEncoder = new JsonEncoderEx(helperWriter, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; notification.Encode(helperEncoder); helperEncoder.Close(); var notificationSize = Encoding.UTF8.GetByteCount(helperWriter.ToString()); if (notificationSize > maxMessageSize) { // we cannot handle this notification. Drop it. // TODO Trace NotificationsDroppedCount++; processing = current.MoveNext(); } else { messageCompleted = maxMessageSize < (messageSize + notificationSize); if (!messageCompleted) { NotificationsProcessedCount++; chunk.Add(notification); processing = current.MoveNext(); messageSize += notificationSize + (processing ? 1 : 0); } } } if (!processing || messageCompleted) { var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext, JsonEncoderEx.JsonEncoding.Array) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; foreach (var element in chunk) { encoder.WriteEncodeable(null, element); } encoder.Close(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.UaJson, MessageSchema = MessageSchemaTypes.NetworkMessageJson }; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + chunk.Count) / (MessagesProcessedCount + 1); MessagesProcessedCount++; chunk.Clear(); messageSize = 2; yield return(encoded); } } }
/// <summary> /// DataSetMessage to NetworkMessage binary batched encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeBatchAsUadp( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { var notifications = GetNetworkMessages(messages, MessageEncoding.Uadp); if (notifications.Count() == 0) { yield break; } // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.First().ServiceMessageContext; var current = notifications.GetEnumerator(); var processing = current.MoveNext(); var messageSize = 4; // array length size maxMessageSize -= 2048; // reserve 2k for header var chunk = new Collection <NetworkMessage>(); while (processing) { var notification = current.Current; var messageCompleted = false; if (notification != null) { var helperEncoder = new BinaryEncoder(encodingContext); helperEncoder.WriteEncodeable(null, notification); var notificationSize = helperEncoder.CloseAndReturnBuffer().Length; if (notificationSize > maxMessageSize) { // we cannot handle this notification. Drop it. // TODO Trace NotificationsDroppedCount++; processing = current.MoveNext(); } else { messageCompleted = maxMessageSize < (messageSize + notificationSize); if (!messageCompleted) { chunk.Add(notification); NotificationsProcessedCount++; processing = current.MoveNext(); messageSize += notificationSize; } } } if (!processing || messageCompleted) { var encoder = new BinaryEncoder(encodingContext); encoder.WriteBoolean(null, true); // is Batch encoder.WriteEncodeableArray(null, chunk); var encoded = new NetworkMessageModel { Body = encoder.CloseAndReturnBuffer(), Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Uadp, MessageSchema = MessageSchemaTypes.NetworkMessageUadp }; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + chunk.Count) / (MessagesProcessedCount + 1); MessagesProcessedCount++; chunk.Clear(); messageSize = 4; yield return(encoded); } } }
/// <summary> /// DataSetMessage to NetworkMessage Json batched encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeBatchAsJson( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.FirstOrDefault(m => m.ServiceMessageContext != null) ?.ServiceMessageContext; var notifications = GetNetworkMessages(messages, MessageEncoding.Json, encodingContext); if (!notifications.Any()) { yield break; } var routingInfo = messages.FirstOrDefault(m => m?.WriterGroup != null)?.WriterGroup.WriterGroupId; var current = notifications.GetEnumerator(); var processing = current.MoveNext(); var messageSize = 2; // array brackets var chunk = new Collection <NetworkMessage>(); int notificationsPerMessage = 0; while (processing) { var notification = current.Current; var messageCompleted = false; if (notification != null) { var helperWriter = new StringWriter(); var helperEncoder = new JsonEncoderEx(helperWriter, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; notification.Encode(helperEncoder); helperEncoder.Close(); var notificationSize = Encoding.UTF8.GetByteCount(helperWriter.ToString()); var notificationsInBatch = notification.Messages.Sum(m => m.Payload.Count); if (notificationSize > maxMessageSize) { // Message too large, drop it. NotificationsDroppedCount += (uint)notificationsInBatch; _logger.Warning("Message too large, dropped {notificationsInBatch} values", notificationsInBatch); processing = current.MoveNext(); } else { messageCompleted = maxMessageSize < (messageSize + notificationSize); if (!messageCompleted) { chunk.Add(notification); NotificationsProcessedCount += (uint)notificationsInBatch; notificationsPerMessage += notificationsInBatch; processing = current.MoveNext(); messageSize += notificationSize + (processing ? 1 : 0); } } } if (messageCompleted || (!processing && chunk.Count > 0)) { var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext, JsonEncoderEx.JsonEncoding.Array) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; foreach (var element in chunk) { encoder.WriteEncodeable(null, element); } encoder.Close(); var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Json, MessageSchema = MessageSchemaTypes.NetworkMessageJson, RoutingInfo = _enableRoutingInfo ? routingInfo : null, }; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + notificationsPerMessage) / (MessagesProcessedCount + 1); MessagesProcessedCount++; chunk.Clear(); messageSize = 2; notificationsPerMessage = 0; yield return(encoded); } } }
/// <summary> /// Perform DataSetMessageModel to NetworkMessageModel batch using Json encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeBatchAsJson( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { var notifications = GetMonitoredItemMessages(messages, MessageEncoding.Json); if (notifications.Count() == 0) { yield break; } var encodingContext = messages.First().ServiceMessageContext; var current = notifications.GetEnumerator(); var processing = current.MoveNext(); var messageSize = 2; // array brackets maxMessageSize -= 2048; // reserve 2k for header var chunk = new Collection <MonitoredItemMessage>(); while (processing) { var notification = current.Current; var messageCompleted = false; if (notification != null) { var helperWriter = new StringWriter(); var helperEncoder = new JsonEncoderEx(helperWriter, encodingContext) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; notification.Encode(helperEncoder); helperEncoder.Close(); var notificationSize = Encoding.UTF8.GetByteCount(helperWriter.ToString()); messageCompleted = maxMessageSize < (messageSize + notificationSize); if (!messageCompleted) { chunk.Add(notification); processing = current.MoveNext(); messageSize += notificationSize + (processing ? 1 : 0); } } if (!processing || messageCompleted) { var writer = new StringWriter(); var encoder = new JsonEncoderEx(writer, encodingContext, JsonEncoderEx.JsonEncoding.Array) { UseAdvancedEncoding = true, UseUriEncoding = true, UseReversibleEncoding = false }; foreach (var element in chunk) { encoder.WriteEncodeable(null, element); } encoder.Close(); chunk.Clear(); messageSize = 2; // array brackets var encoded = new NetworkMessageModel { Body = Encoding.UTF8.GetBytes(writer.ToString()), ContentEncoding = "utf-8", Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.UaJson, MessageSchema = MessageSchemaTypes.MonitoredItemMessageJson }; yield return(encoded); } } }
/// <summary> /// DataSetMessage to NetworkMessage binary batched encoding /// </summary> /// <param name="messages"></param> /// <param name="maxMessageSize"></param> /// <returns></returns> private IEnumerable <NetworkMessageModel> EncodeBatchAsUadp( IEnumerable <DataSetMessageModel> messages, int maxMessageSize) { // by design all messages are generated in the same session context, // therefore it is safe to get the first message's context var encodingContext = messages.FirstOrDefault(m => m.ServiceMessageContext != null) ?.ServiceMessageContext; var notifications = GetNetworkMessages(messages, MessageEncoding.Uadp, encodingContext); if (notifications.Count() == 0) { yield break; } var current = notifications.GetEnumerator(); var processing = current.MoveNext(); var messageSize = 4; // array length size var chunk = new Collection <NetworkMessage>(); int notificationsPerMessage = 0; while (processing) { var notification = current.Current; var messageCompleted = false; if (notification != null) { var helperEncoder = new BinaryEncoder(encodingContext); helperEncoder.WriteEncodeable(null, notification); var notificationSize = helperEncoder.CloseAndReturnBuffer().Length; notificationsPerMessage = notification.Messages.Sum(m => m.Payload.Count); if (notificationSize > maxMessageSize) { // Message too large, drop it. NotificationsDroppedCount += (uint)notificationsPerMessage; _logger.Warning("Message too large, dropped {notificationsPerMessage} values"); processing = current.MoveNext(); } else { messageCompleted = maxMessageSize < (messageSize + notificationSize); if (!messageCompleted) { chunk.Add(notification); NotificationsProcessedCount += (ulong)notificationsPerMessage; processing = current.MoveNext(); messageSize += notificationSize; } } } if (!processing || messageCompleted) { var encoder = new BinaryEncoder(encodingContext); encoder.WriteBoolean(null, true); // is Batch encoder.WriteEncodeableArray(null, chunk); var encoded = new NetworkMessageModel { Body = encoder.CloseAndReturnBuffer(), Timestamp = DateTime.UtcNow, ContentType = ContentMimeType.Uadp, MessageSchema = MessageSchemaTypes.NetworkMessageUadp }; AvgMessageSize = (AvgMessageSize * MessagesProcessedCount + encoded.Body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = (AvgNotificationsPerMessage * MessagesProcessedCount + notificationsPerMessage) / (MessagesProcessedCount + 1); MessagesProcessedCount++; chunk.Clear(); messageSize = 4; notificationsPerMessage = 0; yield return(encoded); } } }