Ejemplo n.º 1
0
        private void CreateWebSocketClient()
        {
            try
            {
                Uri uri = new Uri(String.Format($"wss://{config.Hostname}/ws/connect"));
                cts              = new CancellationTokenSource();
                channel          = new WebSocketClientChannel(uri, "mqtt", new WebSocketConfig(), cts.Token);
                channel.OnClose += Channel_OnClose;
                pclient          = new PiraeusMqttClient(new MqttConfig(180), channel);

                ConnectAckCode code = pclient.ConnectAsync(clientId, "JWT", config.SecurityToken, 90).GetAwaiter().GetResult();
                Console.WriteLine($"MQTT client connection code = {code}");
                if (code != ConnectAckCode.ConnectionAccepted)
                {
                    throw new Exception("MQTT connection failed.");
                }

                pclient.OnChannelError += Pclient_OnChannelError;

                pclient.SubscribeAsync(config.RtuInputPiSystem, QualityOfServiceLevelType.AtLeastOnce, RtuInput).GetAwaiter();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception creating web socket client - {ex.Message}");
                SetDelay();
                CreateWebSocketClient();
            }
        }
Ejemplo n.º 2
0
        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));
            }
        }
Ejemplo n.º 3
0
        public async Task AddSubscriptionAsync(string piSystem, Action <string, string, byte[]> action)
        {
            if (IsConnected)
            {
                await client.SubscribeAsync(piSystem.ToLowerInvariant(), QualityOfServiceLevelType.AtMostOnce, action);

                logger?.LogDebug($"Web socket client subscribed to {piSystem}");
            }
            else
            {
                logger?.LogWarning($"Web socket client is not connected and cannot subscribe to {piSystem}.");
            }
        }
Ejemplo n.º 4
0
        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);
                }
            }
        }
Ejemplo n.º 5
0
        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.");
            }
        }
Ejemplo n.º 6
0
        static async Task StartMqttClientAsync(string token)
        {
            ConnectAckCode code = await MqttConnectAsync(token);

            if (code != ConnectAckCode.ConnectionAccepted)
            {
                return;
            }

            string observableEvent = role == "A" ? "http://www.skunklab.io/resource-b" : "http://www.skunklab.io/resource-a";

            try
            {
                await mqttClient.SubscribeAsync(observableEvent, QualityOfServiceLevelType.AtLeastOnce, ObserveEvent).ContinueWith(SendMessages);
            }
            catch (Exception ex)
            {
                PrintMessage("Error", ConsoleColor.Red, true);
                PrintMessage(ex.Message, ConsoleColor.Red);
                Console.ReadKey();
            }
        }
Ejemplo n.º 7
0
        static async Task StartMqttClientAsync(string token)
        {
            ConnectAckCode code = await MqttConnectAsync(token);

            if (code != ConnectAckCode.ConnectionAccepted)
            {
                return;
            }

            string observableEvent = !string.IsNullOrEmpty(pubResource) ? subResource : role == "A" ? resourceB : resourceA;

            //string observableEvent = role == "A" ? resourceB : resourceA;

            try
            {
                await mqttClient.SubscribeAsync(observableEvent, QualityOfServiceLevelType.AtLeastOnce, ObserveEvent).ContinueWith(SendMessages);
            }
            catch (Exception ex)
            {
                PrintMessage("Error", ConsoleColor.Red, true);
                PrintMessage(ex.Message, ConsoleColor.Red);
                Console.ReadKey();
            }
        }
Ejemplo n.º 8
0
 public async Task SubscribeAsync()
 {
     await mqttClient.SubscribeAsync(inputPiSystem, SkunkLab.Protocols.Mqtt.QualityOfServiceLevelType.AtMostOnce, DiagnosticsAction);
 }
Ejemplo n.º 9
0
        public async Task OpenAsync()
        {
            await ExecuteRetryPolicy();

            subscriptions.Clear();

            if (channel != null)
            {
                try
                {
                    channel.Dispose();
                    channel = null;
                    client  = null;
                    logger?.LogDebug("Disposed internal channel.");
                }
                catch (Exception ex)
                {
                    logger?.LogError(ex, "Fault disposing internal channel.");
                }
            }

            try
            {
                channel = new WebSocketClientChannel(endpointUrl, securityToken, "mqtt", new WebSocketConfig(), CancellationToken.None);
                client  = new PiraeusMqttClient(new MqttConfig(180), channel);
                client.OnChannelError       += Client_OnChannelError;
                client.OnChannelStateChange += Client_OnChannelStateChange;

                string         sessionId = Guid.NewGuid().ToString();
                ConnectAckCode code      = await client.ConnectAsync(sessionId, "JWT", securityToken, 180);

                if (code != ConnectAckCode.ConnectionAccepted)
                {
                    logger?.LogWarning($"Module client connect return code = '{code}'.");
                    OnError?.Invoke(this, new ChannelErrorEventArgs(channel.Id, new Exception($"Module channel failed to open with code = {code}")));
                }
                else
                {
                    logger?.LogInformation("Module client connected.");
                    foreach (var slave in config.Slaves)
                    {
                        string inputPiSystem = UriGenerator.GetRtuPiSystem(config.Hostname, config.VirtualRtuId, config.DeviceId, slave.UnitId, true);
                        await client.SubscribeAsync(inputPiSystem, QualityOfServiceLevelType.AtMostOnce, ModuleReceived);

                        logger?.LogDebug($"Module client subscribed to '{inputPiSystem}'");
                    }

                    try
                    {
                        diag = new DiagnosticsChannel(config, client, logger);
                        diag.StartAsync().GetAwaiter();
                    }
                    catch (Exception ex)
                    {
                        diag = null;
                        logger?.LogError(ex, "Diagnostics channel faulted.");
                    }
                }
            }
            catch (Exception ex)
            {
                logger?.LogError(ex, "Fault opening module channel.");
            }
        }