/// <inheritdoc/> public Task HandleSampleAsync(MonitoredItemSampleModel sample) { // Set timestamp as source timestamp // TODO: Make configurable sample.Timestamp = sample.SourceTimestamp; return(_client.SendAsync(Encoding.UTF8.GetBytes( JsonConvertEx.SerializeObject(sample)))); }
/// <inheritdoc/> public async Task HandleSampleAsync(MonitoredItemSampleModel sample) { var arguments = new object[] { sample.ToApiModel() }; if (!string.IsNullOrEmpty(sample.EndpointId)) { // Send to endpoint listeners await _callback.MulticastAsync(sample.EndpointId, EventTargets.PublisherSampleTarget, arguments); } }
/// <inheritdoc/> private string GetNormalizedEntityName(MonitoredItemSampleModel sample) { if (string.IsNullOrEmpty(sample.PublisherId) || string.IsNullOrEmpty(sample.DataSetWriterId) || string.IsNullOrEmpty(sample.NodeId)) { return(null); } return(GetNormalizedKey($"{sample.PublisherId}_{sample.DataSetWriterId}" + $"_{sample.NodeId}")); }
/// <inheritdoc/> public Task HandleSampleAsync(MonitoredItemSampleModel sample) { // Set timestamp as source timestamp var properties = new Dictionary <string, string>() { [CommonProperties.EventSchemaType] = MessageSchemaTypes.MonitoredItemMessageModelJson }; return(_client.SendAsync(Encoding.UTF8.GetBytes( JsonConvertEx.SerializeObject(sample)), properties)); }
/// <inheritdoc/> public async Task HandleAsync(string deviceId, string moduleId, byte[] payload, IDictionary <string, string> properties, Func <Task> checkpoint) { var json = Encoding.UTF8.GetString(payload); using (var stream = new MemoryStream(payload)) { var context = new ServiceMessageContext(); using (var decoder = new JsonDecoderEx(stream, context)) { var networkMessage = decoder.ReadEncodeable(null, typeof(NetworkMessage)) as NetworkMessage; foreach (var message in networkMessage.Messages) { foreach (var datapoint in message.Payload) { try { var sample = new MonitoredItemSampleModel() { Value = (datapoint.Value?.WrappedValue.Value != null) ? datapoint.Value.WrappedValue.Value : null, Status = StatusCode.LookupSymbolicId(datapoint.Value.StatusCode.Code), TypeId = (datapoint.Value?.WrappedValue.TypeInfo != null) ? TypeInfo.GetSystemType( datapoint.Value.WrappedValue.TypeInfo.BuiltInType, datapoint.Value.WrappedValue.TypeInfo.ValueRank) : null, DataSetId = message.DataSetWriterId, Timestamp = DateTime.UtcNow, SubscriptionId = message.DataSetWriterId, EndpointId = networkMessage.PublisherId, NodeId = datapoint.Key, SourcePicoseconds = datapoint.Value.SourcePicoseconds, ServerPicoseconds = datapoint.Value.ServerPicoseconds, SourceTimestamp = datapoint.Value.SourceTimestamp, ServerTimestamp = datapoint.Value.ServerTimestamp }; if (sample == null) { continue; } await Task.WhenAll(_handlers.Select(h => h.HandleSampleAsync( sample))); } catch (Exception ex) { _logger.Error(ex, "Subscriber message {message} failed with exception - skip", message); } } } } } }
/// <summary> /// Convert to api model /// </summary> /// <param name="model"></param> /// <returns></returns> public static MonitoredItemMessageApiModel ToApiModel( this MonitoredItemSampleModel model) { return(new MonitoredItemMessageApiModel { SubscriptionId = model.SubscriptionId, EndpointId = model.EndpointId, DataSetId = model.DataSetId, NodeId = model.NodeId, ServerPicoseconds = model.ServerPicoseconds, ServerTimestamp = model.ServerTimestamp, SourcePicoseconds = model.SourcePicoseconds, SourceTimestamp = model.SourceTimestamp, Timestamp = model.Timestamp, Value = model.Value }); }
/// <inheritdoc/> public async Task HandleAsync(string deviceId, string moduleId, byte[] payload, IDictionary <string, string> properties, Func <Task> checkpoint) { MonitoredItemMessage message; try { var context = new ServiceMessageContext(); using (var stream = new MemoryStream(payload)) { using (var decoder = new JsonDecoderEx(stream, context)) { var result = decoder.ReadEncodeable(null, typeof(MonitoredItemMessage)) as MonitoredItemMessage; message = result; } } } catch (Exception ex) { _logger.Error(ex, "Failed to decode message"); return; } try { var sample = new MonitoredItemSampleModel() { Value = (message?.Value?.WrappedValue.Value != null) ? message.Value.WrappedValue.Value : null, Status = StatusCode.LookupSymbolicId(message.Value.StatusCode.Code), TypeId = (message?.Value?.WrappedValue.TypeInfo != null) ? TypeInfo.GetSystemType( message.Value.WrappedValue.TypeInfo.BuiltInType, message.Value.WrappedValue.TypeInfo.ValueRank) : null, DataSetId = !string.IsNullOrEmpty(message.DisplayName) ? message.DisplayName : message.NodeId.AsString(null), Timestamp = DateTime.UtcNow, SubscriptionId = message.SubscriptionId, EndpointId = message?.ExtensionFields["EndpointId"], NodeId = message.NodeId.AsString(null), SourcePicoseconds = message.Value.SourcePicoseconds, ServerPicoseconds = message.Value.ServerPicoseconds, SourceTimestamp = message.Value.SourceTimestamp, ServerTimestamp = message.Value.ServerTimestamp }; await Task.WhenAll(_handlers.Select(h => h.HandleSampleAsync(sample))); } catch (Exception ex) { _logger.Error(ex, "Publishing message {message} failed with exception - skip", message); } }
/// <inheritdoc/> public Task HandleSampleAsync(MonitoredItemSampleModel sample) { var cdmModel = new SubscriberCdmSampleModel() { SubscriptionId = sample.SubscriptionId, EndpointId = sample.EndpointId, DataSetId = sample.DataSetId, NodeId = sample.NodeId, Value = sample.Value.ToString(), // Set timestamp as source timestamp - todo make configurable Timestamp = sample.SourceTimestamp, ServerTimestamp = sample.ServerTimestamp, SourceTimestamp = sample.SourceTimestamp }; return(_client.ProcessAsync(cdmModel)); }
/// <summary> /// Clone sample /// </summary> /// <param name="model"></param> /// <returns></returns> public static MonitoredItemSampleModel Clone(this MonitoredItemSampleModel model) { if (model == null) { return(null); } return(new MonitoredItemSampleModel { SubscriptionId = model.SubscriptionId, EndpointId = model.EndpointId, DataSetId = model.DataSetId, NodeId = model.NodeId, ServerPicoseconds = model.ServerPicoseconds, ServerTimestamp = model.ServerTimestamp, SourcePicoseconds = model.SourcePicoseconds, SourceTimestamp = model.SourceTimestamp, Timestamp = model.Timestamp, TypeId = model.TypeId, Value = model.Value, Status = model.Status }); }
/// <summary> /// Convert to api model /// </summary> /// <param name="model"></param> /// <returns></returns> public static MonitoredItemMessageApiModel ToApiModel( this MonitoredItemSampleModel model) { if (model == null) { return(null); } return(new MonitoredItemMessageApiModel { PublisherId = model.PublisherId, DataSetWriterId = model.DataSetWriterId, EndpointId = model.EndpointId, NodeId = model.NodeId, DisplayName = model.DisplayName, ServerTimestamp = model.ServerTimestamp, SourceTimestamp = model.SourceTimestamp, Timestamp = model.Timestamp, Value = model.TypeId?.IsPrimitive == true ? model.Value : model.Value?.ToString(), TypeId = model?.TypeId?.FullName, Status = model.Status }); }
/// <summary> /// Convert to api model /// </summary> /// <param name="model"></param> /// <returns></returns> public static MonitoredItemMessageApiModel ToApiModel( this MonitoredItemSampleModel model) { if (model == null) { return(null); } return(new MonitoredItemMessageApiModel { SubscriptionId = model.SubscriptionId, EndpointId = model.EndpointId, DataSetId = model.DataSetId, NodeId = model.NodeId, ServerPicoseconds = model.ServerPicoseconds, ServerTimestamp = model.ServerTimestamp, SourcePicoseconds = model.SourcePicoseconds, SourceTimestamp = model.SourceTimestamp, Timestamp = model.Timestamp, Value = model.TypeId?.IsPrimitive == true ? model.Value : model.Value?.ToString(), TypeId = model?.TypeId?.FullName, Status = model.Status }); }
private bool GetEntityData(MonitoredItemSampleModel sample, out string partitionLocation, out string partitionDelimitor) { partitionLocation = null; partitionDelimitor = kCsvPartitionsDelimiter; var key = GetNormalizedEntityName(sample.EndpointId, sample.NodeId); var entityDeclaration = Manifest.Entities.Item(key); if (entityDeclaration == null) { return(false); } var partition = entityDeclaration?.DataPartitions[0]; if (partition == null) { return(false); } var csvTrait = partition.ExhibitsTraits.Item("is.partition.format.CSV"); partitionLocation = _cdmCorpus.Storage.CorpusPathToAdapterPath(partition.Location); partitionDelimitor = csvTrait?.Arguments?.FetchValue("delimiter") ?? kCsvPartitionsDelimiter; return(true); }
private bool CreateEntityData(MonitoredItemSampleModel sample, out string partitionLocation, out string partitionDelimitor) { string key = GetNormalizedEntityName(sample.EndpointId, sample.NodeId); // check if the enetity was aleready added var entity = Manifest.Entities.Item(key); if (entity != null) { return(GetEntityData(sample, out partitionLocation, out partitionDelimitor)); } // add a new entity for the Message var newSampleEntity = _cdmCorpus.MakeObject <CdmEntityDefinition>( CdmObjectType.EntityDef, key, false); var info = typeof(MonitoredItemSampleModel).GetProperties(); foreach (var property in info) { // add the attributes required var attribute = _cdmCorpus.MakeObject <CdmTypeAttributeDefinition>( CdmObjectType.TypeAttributeDef, property.Name, false); attribute.Purpose = _cdmCorpus.MakeRef <CdmPurposeReference>( CdmObjectType.PurposeRef, "hasA", true); // if we handle a value, lookup it's type property if (property.Name == "Value" && typeof(MonitoredItemSampleModel). GetProperty("TypeId")?.GetValue(sample) is Type typeId) { attribute.DataFormat = DataTypeToCdmDataFormat(typeId); } else { attribute.DataFormat = DataTypeToCdmDataFormat(property.PropertyType); } attribute.DataType = _cdmCorpus.MakeRef <CdmDataTypeReference>( CdmObjectType.DataTypeRef, DataTypeToCdmDataString(attribute.DataFormat), true); newSampleEntity.Attributes.Add(attribute); } newSampleEntity.DisplayName = kPublisherSampleEntityName; newSampleEntity.Version = "0.0.1"; newSampleEntity.Description = "Opc Ua monitored item sample model"; // Create a new document where the new entity's definition will be stored var newSampleEntityDoc = _cdmCorpus.MakeObject <CdmDocumentDefinition>( CdmObjectType.DocumentDef, $"{newSampleEntity.EntityName}.cdm.json", false); newSampleEntityDoc.Imports.Add($"{newSampleEntity.EntityName}.cdm.json"); // TODO: remove - apparently not necessary //newSampleEntityDoc.Imports.Add(kFoundationJsonPath); newSampleEntityDoc.Definitions.Add(newSampleEntity); _cdmCorpus.Storage.FetchRootFolder("adls").Documents.Add( newSampleEntityDoc, newSampleEntityDoc.Name); var newSampleEntityDef = Manifest.Entities.Add(newSampleEntity); // Define a partition and add it to the local declaration var newSampleEntityPartition = _cdmCorpus.MakeObject <CdmDataPartitionDefinition>( CdmObjectType.DataPartitionDef, newSampleEntity.EntityName); newSampleEntityDef.DataPartitions.Add(newSampleEntityPartition); newSampleEntityPartition.Location = $"adls:/{newSampleEntity.EntityName}/partition-data.csv"; newSampleEntityPartition.Explanation = "Opc Ua monitored item sample messages storage"; var csvTrait = newSampleEntityPartition.ExhibitsTraits.Add( "is.partition.format.CSV"); csvTrait.Arguments.Add("columnHeaders", "true"); csvTrait.Arguments.Add("delimiter", kCsvPartitionsDelimiter); partitionLocation = _cdmCorpus.Storage.CorpusPathToAdapterPath(newSampleEntityPartition.Location); partitionDelimitor = csvTrait?.Arguments?.FetchValue("delimiter") ?? kCsvPartitionsDelimiter; return(true); }
/// <inheritdoc/> private CdmDataPartitionDefinition GetOrCreateEntityDataPartition(string key, MonitoredItemSampleModel sample, out bool persist, bool forceNew = false) { persist = false; if (string.IsNullOrEmpty(key) || sample == null) { return(null); } // check if the enetity was aleready added var entityDefinition = Manifest.Entities.Item(key); if (entityDefinition == null) { // add a new entity for the sample // add a new entity for the Message var newSampleEntity = _cdmCorpus.MakeObject <CdmEntityDefinition>( CdmObjectType.EntityDef, key, false); var info = typeof(MonitoredItemSampleModel).GetProperties(); foreach (var property in info) { // add the attributes required var attribute = _cdmCorpus.MakeObject <CdmTypeAttributeDefinition>( CdmObjectType.TypeAttributeDef, property.Name, false); attribute.Purpose = _cdmCorpus.MakeRef <CdmPurposeReference>( CdmObjectType.PurposeRef, "hasA", true); // if we handle a value, lookup it's type property if (property.Name == "Value") { attribute.DataFormat = DataTypeToCdmDataFormat(sample.Value.GetType()); } else { attribute.DataFormat = DataTypeToCdmDataFormat(property.PropertyType); } newSampleEntity.Attributes.Add(attribute); } newSampleEntity.DisplayName = kPublisherSampleEntityName; newSampleEntity.Version = "0.0.2"; newSampleEntity.Description = "Opc Ua Monitored Item Sample"; // Create a new document where the new entity's definition will be stored var newSampleEntityDoc = _cdmCorpus.MakeObject <CdmDocumentDefinition>( CdmObjectType.DocumentDef, $"{newSampleEntity.EntityName}.cdm.json", false); newSampleEntityDoc.Imports.Add($"{newSampleEntity.EntityName}.cdm.json"); // TODO: remove - apparently not necessary newSampleEntityDoc.Imports.Add(kFoundationJsonPath); newSampleEntityDoc.Definitions.Add(newSampleEntity); _cdmCorpus.Storage.FetchRootFolder("adls").Documents.Add( newSampleEntityDoc, newSampleEntityDoc.Name); entityDefinition = Manifest.Entities.Add(newSampleEntity); persist |= true; } var partition = entityDefinition.DataPartitions.Count != 0 ? entityDefinition.DataPartitions.Last() : null; if (forceNew || partition == null) { // Define a partition and add it to the local declaration var newPartition = _cdmCorpus.MakeObject <CdmDataPartitionDefinition>( CdmObjectType.DataPartitionDef, entityDefinition.EntityName); var timestamp = DateTime.UtcNow.ToString( "yyMMddHHmmss", DateTimeFormatInfo.InvariantInfo); newPartition.Location = $"adls:/{entityDefinition.EntityName}/partition-data-{timestamp}.csv"; newPartition.Explanation = "OPC UA PubSub DataSet Partition"; var partitionTrait = newPartition.ExhibitsTraits.Add( "is.partition.format.CSV"); partitionTrait.Arguments.Add("columnHeaders", "true"); partitionTrait.Arguments.Add("delimiter", kCsvPartitionsDelimiter); partition = entityDefinition.DataPartitions.Add(newPartition); persist |= true; } return(partition); }
/// <inheritdoc/> public Task HandleSampleAsync(MonitoredItemSampleModel sample) { return(_client.ProcessAsync(sample)); }