/// <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);
         }
     }
 }
예제 #2
0
 /// <inheritdoc/>
 public JToken Encode(Variant value, out BuiltInType builtinType,
                      ServiceMessageContext context)
 {
     if (value == Variant.Null)
     {
         builtinType = BuiltInType.Null;
         return(JValue.CreateNull());
     }
     using (var stream = new MemoryStream()) {
         using (var encoder = new JsonEncoderEx(stream,
                                                context ?? Context)
         {
             UseAdvancedEncoding = true
         }) {
             encoder.WriteVariant(nameof(value), value);
         }
         var json = Encoding.UTF8.GetString(stream.ToArray());
         try {
             var token = JToken.Parse(json);
             Enum.TryParse((string)token.SelectToken("value.Type"),
                           true, out builtinType);
             return(token.SelectToken("value.Body"));
         }
         catch (JsonReaderException jre) {
             throw new FormatException($"Failed to parse '{json}'. " +
                                       "See inner exception for more details.", jre);
         }
     }
 }
예제 #3
0
        /// <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);
         }
     }
 }
        public void EncodeDecodeNetworkMessage()
        {
            var payload = new Dictionary <string, DataValue> {
                { "1", new DataValue(new Variant(5), StatusCodes.Good, DateTime.Now) },
                { "2", new DataValue(new Variant(0.5), StatusCodes.Good, DateTime.Now) },
                { "3", new DataValue("abcd") }
            };

            var message = new DataSetMessage {
                DataSetWriterId = "WriterId",
                MetaDataVersion = new ConfigurationVersionDataType {
                    MajorVersion = 1, MinorVersion = 1
                },
                SequenceNumber     = ++_currentSequenceNumber,
                Status             = StatusCodes.Good,
                Timestamp          = DateTime.UtcNow,
                MessageContentMask = (uint)(
                    JsonDataSetMessageContentMask.DataSetWriterId |
                    JsonDataSetMessageContentMask.SequenceNumber |
                    JsonDataSetMessageContentMask.MetaDataVersion |
                    JsonDataSetMessageContentMask.Timestamp |
                    JsonDataSetMessageContentMask.Status),
                Payload = new DataSet(payload)
                {
                    FieldContentMask = (uint)(DataSetFieldContentMask.StatusCode | DataSetFieldContentMask.SourceTimestamp)
                }
            };

            var networkMessage = new NetworkMessage {
                MessageId   = Guid.NewGuid().ToString(), // TODO
                MessageType = "ua-data",
                Messages    = new List <DataSetMessage>(),
                PublisherId = "PublisherId"
            };

            networkMessage.Messages.Add(message);
            networkMessage.MessageContentMask = (uint)(
                JsonNetworkMessageContentMask.PublisherId |
                JsonNetworkMessageContentMask.NetworkMessageHeader |
                JsonNetworkMessageContentMask.SingleDataSetMessage);

            byte[] buffer;
            string json;
            var    context = new ServiceMessageContext();

            using (var stream = new MemoryStream()) {
                using (var encoder = new JsonEncoderEx(stream, context)) {
                    networkMessage.Encode(encoder);
                }
                buffer = stream.ToArray();
                json   = buffer.ToBase16String();
            }

            using (var stream = new MemoryStream(buffer)) {
                using (var decoder = new JsonDecoderEx(stream, context)) {
                    var result = decoder.ReadEncodeable(null, typeof(NetworkMessage)) as NetworkMessage;
                    Assert.Equal(networkMessage, result);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Convert operation results to json
        /// </summary>
        /// <param name="results"></param>
        /// <param name="config"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        private static JToken ToJson(this List <OperationResultModel> results, DiagnosticsModel config,
                                     ServiceMessageContext context)
        {
            var level = config?.Level ?? Twin.Models.DiagnosticsLevel.Status;

            if (level == Twin.Models.DiagnosticsLevel.None)
            {
                return(null);
            }
            using (var stream = new MemoryStream()) {
                var root = kDiagnosticsProperty;
                using (var encoder = new JsonEncoderEx(stream, context)
                {
                    UseAdvancedEncoding = true,
                    IgnoreDefaultValues = true
                }) {
                    switch (level)
                    {
                    case Twin.Models.DiagnosticsLevel.Diagnostics:
                    case Twin.Models.DiagnosticsLevel.Verbose:
                        encoder.WriteEncodeableArray(root, results);
                        break;

                    case Twin.Models.DiagnosticsLevel.Operations:
                        var codes = results
                                    .GroupBy(d => d.StatusCode.CodeBits);
                        root = null;
                        foreach (var code in codes)
                        {
                            encoder.WriteStringArray(StatusCode.LookupSymbolicId(code.Key),
                                                     code.Select(c => c.Operation).ToArray());
                        }
                        break;

                    case Twin.Models.DiagnosticsLevel.Status:
                        var statusCodes = results
                                          .Select(d => StatusCode.LookupSymbolicId(d.StatusCode.CodeBits))
                                          .Where(s => !string.IsNullOrEmpty(s))
                                          .Distinct();
                        if (!statusCodes.Any())
                        {
                            return(null);
                        }
                        encoder.WriteStringArray(root, statusCodes.ToArray());
                        break;
                    }
                }
                var o = JObject.Parse(Encoding.UTF8.GetString(stream.ToArray()));
                return(root != null?o.Property(root).Value : o);
            }
        }
        /// <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>
 /// Writes collection as json
 /// </summary>
 /// <param name="collection"></param>
 /// <param name="context"></param>
 /// <param name="formatting"></param>
 /// <param name="ostrm"></param>
 public static void SaveAsJson(this NodeStateCollection collection, Stream ostrm,
                               Newtonsoft.Json.Formatting formatting, ISystemContext context)
 {
     using (var encoder = new JsonEncoderEx(ostrm, context.ToMessageContext(),
                                            JsonEncoderEx.JsonEncoding.Array, formatting)
     {
         UseAdvancedEncoding = true,
         IgnoreDefaultValues = true
     }) {
         foreach (var node in collection.ToNodeModels(context))
         {
             if (node != null)
             {
                 encoder.WriteEncodeable(null, new EncodeableNodeModel(node));
             }
         }
     }
 }
 /// <inheritdoc/>
 public VariantValue Encode(Variant?value, out BuiltInType builtinType)
 {
     if (value == null || value == Variant.Null)
     {
         builtinType = BuiltInType.Null;
         return(VariantValue.Null);
     }
     using (var stream = new MemoryStream()) {
         using (var encoder = new JsonEncoderEx(stream, Context)
         {
             UseAdvancedEncoding = true
         }) {
             encoder.WriteVariant(nameof(value), value.Value);
         }
         var token = Serializer.Parse(stream.ToArray());
         Enum.TryParse((string)token.GetByPath("value.Type"),
                       true, out builtinType);
         return(token.GetByPath("value.Body"));
     }
 }
예제 #11
0
 /// <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);
         }
     }
 }
예제 #12
0
 /// <summary>
 /// Test model browse encoder
 /// </summary>
 private static async Task TestOpcUaModelExportServiceAsync(EndpointModel endpoint)
 {
     using (var logger = StackLogger.Create(ConsoleLogger.Create()))
         using (var client = new ClientServices(logger.Logger, new TestClientServicesConfig()))
             using (var server = new ServerWrapper(endpoint, logger))
                 using (var stream = Console.OpenStandardOutput())
                     using (var writer = new StreamWriter(stream))
                         using (var json = new JsonTextWriter(writer)
                         {
                             AutoCompleteOnClose = true,
                             Formatting = Formatting.Indented,
                             DateFormatHandling = DateFormatHandling.IsoDateFormat
                         })
                             using (var encoder = new JsonEncoderEx(json, null,
                                                                    JsonEncoderEx.JsonEncoding.Array)
                             {
                                 IgnoreDefaultValues = true,
                                 UseAdvancedEncoding = true
                             })
                                 using (var browser = new BrowseStreamEncoder(client, endpoint, encoder,
                                                                              null, logger.Logger, null)) {
                                     await browser.EncodeAsync(CancellationToken.None);
                                 }
 }
예제 #13
0
            /// <inheritdoc/>
            public async Task SendEventAsync(byte[] data, string contentType,
                                             string eventSchema, string contentEncoding)
            {
                var ev = JsonConvert.DeserializeObject <DiscoveryEventModel>(
                    Encoding.UTF8.GetString(data));
                var endpoint = ev.Registration?.Endpoint;

                if (endpoint == null)
                {
                    return;
                }
                try {
                    var id = endpoint.Url.ToSha1Hash();
                    _logger.Information("Writing {id}.json for {@ev}", id, ev);
                    using (var writer = File.CreateText($"iop_{id}.json"))
                        using (var json = new JsonTextWriter(writer)
                        {
                            AutoCompleteOnClose = true,
                            Formatting = Formatting.Indented,
                            DateFormatHandling = DateFormatHandling.IsoDateFormat
                        })
                            using (var encoder = new JsonEncoderEx(json, null,
                                                                   JsonEncoderEx.JsonEncoding.Array)
                            {
                                IgnoreDefaultValues = true,
                                UseAdvancedEncoding = true
                            })
                                using (var browser = new BrowseStreamEncoder(_client, endpoint, encoder,
                                                                             null, _logger, null)) {
                                    await browser.EncodeAsync(CancellationToken.None);
                                }
                }
                catch (Exception ex) {
                    _logger.Error(ex, "Failed to browse");
                }
            }
        /// <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 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);
                }
            }
        }
예제 #16
0
        /// <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);
                }
            }
        }
        public void EncodeDecodeNetworkMessageFull()
        {
            var payload = new Dictionary <string, DataValue> {
                ["abcd"] = new DataValue(new Variant(1234), StatusCodes.Good, DateTime.Now, DateTime.UtcNow),
                ["http://microsoft.com"]      = new DataValue(new Variant(-222222222), StatusCodes.Bad, DateTime.MinValue, DateTime.Now),
                ["1111111111111111111111111"] = new DataValue(new Variant(false), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue),
                ["@#$%^&*()_+~!@#$%^*(){}"]   = new DataValue(new Variant(new byte[] { 0, 2, 4, 6 }), StatusCodes.Good),
                ["1245"] = new DataValue(new Variant("hello"), StatusCodes.Bad, DateTime.Now, DateTime.MinValue),
                ["..."]  = new DataValue(new Variant(new Variant("imbricated")))
            };

            var message = new DataSetMessage {
                DataSetWriterId = "WriterId",
                MetaDataVersion = new ConfigurationVersionDataType {
                    MajorVersion = 1, MinorVersion = 1
                },
                SequenceNumber     = ++_currentSequenceNumber,
                Status             = StatusCodes.Good,
                Timestamp          = DateTime.UtcNow,
                Picoseconds        = 1234,
                MessageContentMask = (uint)(
                    JsonDataSetMessageContentMask.DataSetWriterId |
                    JsonDataSetMessageContentMask.SequenceNumber |
                    JsonDataSetMessageContentMask.MetaDataVersion |
                    JsonDataSetMessageContentMask.Timestamp |
                    JsonDataSetMessageContentMask.Status),
                Payload = new DataSet(payload, (uint)(
                                          DataSetFieldContentMask.StatusCode |
                                          DataSetFieldContentMask.SourceTimestamp |
                                          DataSetFieldContentMask.ServerTimestamp |
                                          DataSetFieldContentMask.SourcePicoSeconds |
                                          DataSetFieldContentMask.ServerPicoSeconds))
            };

            var networkMessage = new NetworkMessage {
                MessageId      = Guid.NewGuid().ToString(), // TODO
                MessageType    = "ua-data",
                Messages       = new List <DataSetMessage>(),
                PublisherId    = "PublisherId",
                DataSetClassId = "1234"
            };

            networkMessage.Messages.Add(message);
            networkMessage.MessageContentMask = (uint)(
                JsonNetworkMessageContentMask.PublisherId |
                JsonNetworkMessageContentMask.NetworkMessageHeader |
                JsonNetworkMessageContentMask.SingleDataSetMessage |
                JsonNetworkMessageContentMask.DataSetClassId);

            byte[] buffer;
            var    context = new ServiceMessageContext();

            using (var stream = new MemoryStream()) {
                using (var encoder = new JsonEncoderEx(stream, context)) {
                    networkMessage.Encode(encoder);
                }
                buffer = stream.ToArray();
            }

            ConvertToOpcUaUniversalTime(networkMessage);

            using (var stream = new MemoryStream(buffer)) {
                using (var decoder = new JsonDecoderEx(stream, context)) {
                    var result = decoder.ReadEncodeable(null, typeof(NetworkMessage)) as NetworkMessage;
                    Assert.Equal(networkMessage, result);
                }
            }
        }