private void Channel_OnReceive(object sender, ChannelReceivedEventArgs e) { try { MbapHeader header = MbapHeader.Decode(e.Message); if (!unitId.HasValue) { unitId = header.UnitId; } if (unitId.HasValue && header.UnitId == unitId.Value) { RtuPiSystem piSystem = map.GetItem((ushort)unitId.Value); if (piSystem == null) { throw new Exception($"PI-System not found for unit id - {unitId.Value}"); } else { client.SubscribeAsync(piSystem.RtuOutputEvent, QualityOfServiceLevelType.AtLeastOnce, ReceiveOutput).GetAwaiter(); client.PublishAsync(QualityOfServiceLevelType.AtLeastOnce, piSystem.RtuInputEvent, contentType, e.Message).GetAwaiter(); } } else { throw new Exception("Unit Id missing from SCADA client message."); } } catch (Exception ex) { OnError?.Invoke(this, new AdapterErrorEventArgs(Id, ex)); } }
static void SendMessages(Task task) { try { if (!send) { PrintMessage("Do you want to send messages (Y/N) ? ", ConsoleColor.Cyan, false, true); string sendVal = Console.ReadLine(); if (sendVal.ToUpperInvariant() != "Y") { return; } } send = true; PrintMessage("Enter # of messages to send ? ", ConsoleColor.Cyan, false, true); string nstring = Console.ReadLine(); int numMessages = Int32.Parse(nstring); PrintMessage("Enter delay between messages in milliseconds ? ", ConsoleColor.Cyan, false, true); string dstring = Console.ReadLine().Trim(); int delayms = Int32.Parse(dstring); DateTime startTime = DateTime.Now; for (int i = 0; i < numMessages; i++) { index++; string payloadString = String.Format($"{DateTime.Now.Ticks}:{name}-message {index}"); byte[] payload = Encoding.UTF8.GetBytes(payloadString); string publishEvent = !string.IsNullOrEmpty(pubResource) ? pubResource : role == "A" ? resourceA : resourceB; //string publishEvent = role == "A" ? "http://www.skunklab.io/resource-a" : "http://www.skunklab.io/resource-b"; Task pubTask = mqttClient.PublishAsync(QualityOfServiceLevelType.AtMostOnce, publishEvent, "text/plain", payload); Task.WhenAll(pubTask); if (delayms > 0) { Task t = Task.Delay(delayms); Task.WaitAll(t); } } DateTime endTime = DateTime.Now; PrintMessage($"Total send time {endTime.Subtract(startTime).TotalMilliseconds} ms", ConsoleColor.White); PrintMessage("Send more messages (Y/N) ? ", ConsoleColor.Cyan, false, true); string val = Console.ReadLine(); if (val.ToUpperInvariant() == "Y") { SendMessages(task); } } catch (Exception ex) { PrintMessage("Error", ConsoleColor.Red, true); PrintMessage(ex.Message, ConsoleColor.Red); Console.ReadKey(); } }
public async Task SubscribeAsync(string resource, bool monitor) { string monitorUriString = null; string logUriString = null; string[] parts = resource.Split(new[] { "-" }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 1) { //virtual rtu monitorUriString = UriGenerator.GetVirtualRtuDiagnosticsPiSystem(hostname, parts[0]); logUriString = UriGenerator.GetVirtualRtuTelemetryPiSystem(hostname, parts[0]); } else if (parts.Length == 2) { //module monitorUriString = UriGenerator.GetDeviceDiagnosticsPiSystem(hostname, parts[0], parts[1]); logUriString = UriGenerator.GetDeviceTelemetryPiSystem(hostname, parts[0], parts[1]); } DiagnosticsMessage mevent = new DiagnosticsMessage { Type = monitor ? DiagnosticsEventType.Native : DiagnosticsEventType.None }; string jsonString = JsonConvert.SerializeObject(mevent); await client.PublishAsync(QualityOfServiceLevelType.AtMostOnce, monitorUriString, "application/json", Encoding.UTF8.GetBytes(jsonString)); if (monitor) { if (!subscriptions.Contains(logUriString)) { subscriptions.Add(logUriString); await client.SubscribeAsync(logUriString, QualityOfServiceLevelType.AtMostOnce, ReceiveLog); } } else { if (subscriptions.Contains(logUriString)) { subscriptions.Remove(logUriString); await client.UnsubscribeAsync(logUriString); } } }
public async Task PublishOutput(MbapHeader header, ushort transactionId) { if (!NativeEnabled && !AppInsightsEnabled) { return; } DiagnosticsEvent telem = new DiagnosticsEvent(name, header.UnitId, transactionId, header.TransactionId, DateTime.UtcNow.ToString("dd-MM-yyyyThh:mm:ss.ffff")); if (NativeEnabled && mqttClient.IsConnected) { string jsonString = JsonConvert.SerializeObject(telem); byte[] msg = Encoding.UTF8.GetBytes(jsonString); await mqttClient.PublishAsync(QualityOfServiceLevelType.AtMostOnce, outputPiSystem, "application/json", msg); } if (AppInsightsEnabled) { tclient?.TrackEvent(name, telem.GetEventProperties(), telem.GetEventMetrics()); } if (cache.Contains(transactionId.ToString())) { Tuple <byte, long> tuple = cache.Get <Tuple <byte, long> >(transactionId.ToString()); cache.Remove(transactionId.ToString()); TimeSpan ts = TimeSpan.FromTicks(DateTime.Now.Ticks - tuple.Item2); DiagnosticsEvent vdts = new DiagnosticsEvent(name, header.UnitId, transactionId, ts.TotalMilliseconds, DateTime.UtcNow.ToString("dd-MM-yyyyThh:mm:ss.ffff")); if (NativeEnabled && mqttClient != null && mqttClient.IsConnected) { string jsonString = JsonConvert.SerializeObject(vdts); byte[] data = Encoding.UTF8.GetBytes(jsonString); await mqttClient.PublishAsync(QualityOfServiceLevelType.AtMostOnce, outputPiSystem, "application/json", data); } if (AppInsightsEnabled) { tclient?.TrackEvent(name, vdts.GetEventProperties(), vdts.GetEventMetrics()); } } }
public async Task PublishInput(MbapHeader header) { if (!NativeEnabled && !AppInsightsEnabled) { return; } DiagnosticsEvent telem = new DiagnosticsEvent(name, header.UnitId, header.TransactionId, DateTime.UtcNow.ToString("dd-MM-yyyyThh:mm:ss.ffff")); cache.Add(header.TransactionId.ToString(), DateTime.Now.Ticks, 20); if (NativeEnabled && mqttClient != null && mqttClient.IsConnected) { string jsonString = JsonConvert.SerializeObject(telem); byte[] msg = Encoding.UTF8.GetBytes(jsonString); await mqttClient.PublishAsync(SkunkLab.Protocols.Mqtt.QualityOfServiceLevelType.AtMostOnce, outputPiSystem, "application/json", msg); } if (AppInsightsEnabled) { tclient?.TrackEvent(name, telem.GetEventProperties(), telem.GetEventMetrics()); } }
public async Task SendAsync(byte[] message) { if (client == null || !client.IsConnected) { logger?.LogWarning("MQTT client is not available to forward message."); return; } try { MbapHeader header = MbapHeader.Decode(message); if (map.HasItem(header.UnitId)) { if (!subscriptions.Contains(header.UnitId)) { string resource = map.GetItem(header.UnitId).RtuOutputEvent; await client.SubscribeAsync(resource, QualityOfServiceLevelType.AtMostOnce, ModbusMessageReceived); logger?.LogInformation( $"MQTT client channel subscribed {resource} with Unit ID = {header.UnitId}"); subscriptions.Add(header.UnitId); } cache.Add(GetCacheKey(header), new Tuple <ushort, byte[]>(header.TransactionId, message), 20.0); string pisystem = map.GetItem(header.UnitId).RtuInputEvent; await client.PublishAsync(QualityOfServiceLevelType.AtMostOnce, pisystem, "application/octet-stream", message); logger?.LogDebug($"VRTU published to {pisystem}"); await diag?.PublishInput(header); } else { logger?.LogWarning($"Unit Id = {header.UnitId} in Modbus message not found in RTU map."); } } catch (Exception ex) { logger?.LogError(ex, "Fault sending MQTT client channel."); } }
public async Task SendAsync(byte[] message) { if (client == null || !client.IsConnected) { logger?.LogWarning("Module channel client is unavailable to send."); return; } try { MbapHeader header = MbapHeader.Decode(message); string pisystem = UriGenerator.GetRtuPiSystem(hostname, virtualRtuId, deviceId, header.UnitId, false); await client.PublishAsync(QualityOfServiceLevelType.AtMostOnce, pisystem, "application/json", message); await diag?.PublishOutput(header); logger?.LogDebug("Published message on module channel"); } catch (Exception ex) { logger?.LogError(ex, "Fault sending on module channel."); } }
public async Task SendRtuOutputAsync(byte[] message) { await pclient.PublishAsync(QualityOfServiceLevelType.AtLeastOnce, config.RtuOutputPiSsytem, Constants.CONTENT_TYPE, message); }
public async Task SendAsync(string pisystem, string contentType, byte[] message) { await client.PublishAsync(QualityOfServiceLevelType.AtMostOnce, pisystem, contentType, message); }