/// <summary> /// Analyze payload of IoTHub message, adding timestamp and related sequence numbers into temporary /// </summary> /// <param name="arg"></param> /// <returns>Task that run until token is canceled</returns> private Task Client_ProcessEventAsync(ProcessEventArgs arg) { var eventReceivedTimestamp = DateTime.UtcNow; // Check if already stopped. if (_cancellationTokenSource == null) { _logger.LogWarning("Received Events but nothing to do, because already stopped"); return(Task.CompletedTask); } if (!arg.HasEvent) { _logger.LogWarning("Received partition event without content"); return(Task.CompletedTask); } var body = arg.Data.Body.ToArray(); var content = Encoding.UTF8.GetString(body); dynamic json = JsonConvert.DeserializeObject(content); var valueChangesCount = 0; // TODO build variant that works with PubSub foreach (dynamic entry in json) { DateTime entrySourceTimestamp; string entryNodeId = null; object entryValue; try { entrySourceTimestamp = (DateTime)entry.Value.SourceTimestamp; entryNodeId = entry.NodeId; entryValue = entry.Value.Value; } catch (Exception ex) { _logger.LogError(ex, "Could not read sequence number, nodeId and/or timestamp from " + "message. Please make sure that publisher is running with samples format and with " + "--fm parameter set."); continue; } // Feed data to checkers. _missingTimestampsChecker.ProcessEvent(entryNodeId, entrySourceTimestamp, entryValue); _messageProcessingDelayChecker.ProcessEvent(entrySourceTimestamp, eventReceivedTimestamp); _messageDeliveryDelayChecker.ProcessEvent(entrySourceTimestamp, arg.Data.EnqueuedTime.UtcDateTime); _valueChangeCounterPerNodeId.ProcessEvent(entryNodeId, entrySourceTimestamp, entryValue); _missingValueChangesChecker.ProcessEvent(entrySourceTimestamp); _incrementalIntValueChecker.ProcessEvent(entryNodeId, entryValue); Interlocked.Increment(ref _totalValueChangesCount); valueChangesCount++; } _logger.LogDebug("Received {NumberOfValueChanges} messages from IoT Hub, partition {PartitionId}.", valueChangesCount, arg.Partition.PartitionId); return(Task.CompletedTask); }
/// <summary> /// Feed the checkers for the Value Change (single Node value) within the reveived event /// </summary> /// <param name="nodeId">Identifeir of the data source.</param> /// <param name="sourceTimestamp">Timestamp at the Data Source.</param> /// <param name="enqueuedTimestamp">IoT Hub message enqueue timestamp.</param> /// <param name="receivedTimestamp">Timestamp of arrival in the telemetry processor.</param> /// <param name="value">The actual value of the data change.</param> private void FeedDataCheckers( string nodeId, DateTime sourceTimestamp, DateTime enqueuedTimestamp, DateTime receivedTimestamp, object value) { // OPC PLC contains bad fast and slow nodes that drop messages by design. // We will ignore entries that do not have a value. if (value is null) { return; } // Feed data to checkers. _missingTimestampsChecker.ProcessEvent(nodeId, sourceTimestamp, value); _messageProcessingDelayChecker.ProcessEvent(nodeId, sourceTimestamp, receivedTimestamp); _messageDeliveryDelayChecker.ProcessEvent(nodeId, sourceTimestamp, enqueuedTimestamp); _valueChangeCounterPerNodeId.ProcessEvent(nodeId, sourceTimestamp, value); _missingValueChangesChecker.ProcessEvent(sourceTimestamp); _incrementalIntValueChecker.ProcessEvent(nodeId, sourceTimestamp, value); Interlocked.Increment(ref _totalValueChangesCount); }