/// <inheritdoc/>
        public async Task HandleAsync(string deviceId, string moduleId,
                                      byte[] payload, IDictionary <string, string> properties, Func <Task> checkpoint)
        {
            try {
                var context  = new ServiceMessageContext();
                var decoder  = new BinaryDecoder(new MemoryStream(payload), context);
                var messages = decoder.ReadBoolean(null) // is Batch?
                    ? decoder.ReadEncodeableArray(null, typeof(NetworkMessage))
                               as NetworkMessage[]
                     : (decoder.ReadEncodeable(null, typeof(NetworkMessage))
                        as NetworkMessage).YieldReturn();

                foreach (var message in messages)
                {
                    foreach (var dataSetMessage in message.Messages)
                    {
                        var dataset = new DataSetMessageModel {
                            PublisherId     = message.PublisherId,
                            MessageId       = message.MessageId,
                            DataSetClassId  = message.DataSetClassId,
                            DataSetWriterId = dataSetMessage.DataSetWriterId,
                            SequenceNumber  = dataSetMessage.SequenceNumber,
                            Status          = StatusCode.LookupSymbolicId(dataSetMessage.Status.Code),
                            MetaDataVersion = $"{dataSetMessage.MetaDataVersion.MajorVersion}" +
                                              $".{dataSetMessage.MetaDataVersion.MinorVersion}",
                            Timestamp = dataSetMessage.Timestamp,
                            Payload   = new Dictionary <string, DataValueModel>()
                        };
                        foreach (var datapoint in dataSetMessage.Payload)
                        {
                            var codec = _encoder.Create(context);
                            var type  = BuiltInType.Null;
                            dataset.Payload[datapoint.Key] = new DataValueModel {
                                Value = datapoint.Value == null
                                    ? null : codec.Encode(datapoint.Value.WrappedValue, out type),
                                DataType = type == BuiltInType.Null
                                    ? null : type.ToString(),
                                Status = (datapoint.Value?.StatusCode.Code == StatusCodes.Good)
                                    ? null : StatusCode.LookupSymbolicId(datapoint.Value.StatusCode.Code),
                                SourceTimestamp = (datapoint.Value?.SourceTimestamp == DateTime.MinValue)
                                    ? null : datapoint.Value?.SourceTimestamp,
                                SourcePicoseconds = (datapoint.Value?.SourcePicoseconds == 0)
                                    ? null : datapoint.Value?.SourcePicoseconds,
                                ServerTimestamp = (datapoint.Value?.ServerTimestamp == DateTime.MinValue)
                                    ? null : datapoint.Value?.ServerTimestamp,
                                ServerPicoseconds = (datapoint.Value?.ServerPicoseconds == 0)
                                    ? null : datapoint.Value?.ServerPicoseconds
                            };
                        }
                        await Task.WhenAll(_handlers.Select(h => h.HandleMessageAsync(dataset)));
                    }
                }
            }
            catch (Exception ex) {
                _logger.Error(ex, "Subscriber binary network message handling failed - skip");
            }
        }
        /// <inheritdoc/>
        public async Task HandleAsync(string deviceId, string moduleId,
                                      byte[] payload, IDictionary <string, string> properties, Func <Task> checkpoint)
        {
            try {
                var context  = new ServiceMessageContext();
                var decoder  = new BinaryDecoder(new MemoryStream(payload), context);
                var messages = decoder.ReadBoolean(null) // is Batch?
                    ? decoder.ReadEncodeableArray(null, typeof(MonitoredItemMessage))
                               as MonitoredItemMessage[]
                     : (decoder.ReadEncodeable(null, typeof(MonitoredItemMessage))
                        as MonitoredItemMessage).YieldReturn();

                foreach (var message in messages)
                {
                    var type    = BuiltInType.Null;
                    var codec   = _encoder.Create(context);
                    var dataset = new DataSetMessageModel {
                        PublisherId = (message.ExtensionFields != null &&
                                       message.ExtensionFields.TryGetValue("PublisherId", out var publisherId))
                                ? publisherId : message.ApplicationUri ?? message.EndpointUrl,
                        MessageId       = null,
                        DataSetClassId  = message.NodeId.AsString(null),
                        DataSetWriterId = (message.ExtensionFields != null &&
                                           message.ExtensionFields.TryGetValue("DataSetWriterId", out var dataSetWriterId))
                                ? dataSetWriterId : message.EndpointUrl ?? message.ApplicationUri,
                        SequenceNumber  = message.SequenceNumber,
                        Status          = StatusCode.LookupSymbolicId(message.Value.StatusCode.Code),
                        MetaDataVersion = "1.0",
                        Timestamp       = message.Timestamp,
                        Payload         = new Dictionary <string, DataValueModel>()
                        {
                            [message.NodeId.AsString(context)] = new DataValueModel {
                                Value = message?.Value == null
                                    ? null : codec.Encode(message.Value.WrappedValue, out type),
                                DataType = type == BuiltInType.Null
                                    ? null : type.ToString(),
                                Status = (message?.Value?.StatusCode.Code == StatusCodes.Good)
                                    ? null : StatusCode.LookupSymbolicId(message.Value.StatusCode.Code),
                                SourceTimestamp = (message?.Value?.SourceTimestamp == DateTime.MinValue)
                                    ? null : message?.Value?.SourceTimestamp,
                                SourcePicoseconds = (message?.Value?.SourcePicoseconds == 0)
                                    ? null : message?.Value?.SourcePicoseconds,
                                ServerTimestamp = (message?.Value?.ServerTimestamp == DateTime.MinValue)
                                    ? null : message?.Value?.ServerTimestamp,
                                ServerPicoseconds = (message?.Value?.ServerPicoseconds == 0)
                                    ? null : message?.Value?.ServerPicoseconds,
                            }
                        }
                    };
                    await Task.WhenAll(_handlers.Select(h => h.HandleMessageAsync(dataset)));
                }
            }
            catch (Exception ex) {
                _logger.Error(ex, "Publishing messages failed - skip");
            }
        }