Beispiel #1
0
        private static IMqttClientOptions MakeMqttOptions(string certDir, MqttConfig config, string suffix)
        {
            string clientID = $"{config.ClientIDPrefix}_{suffix}_{TheGuid}";

            var builder = new MqttClientOptionsBuilder()
                          .WithClientId(clientID)
                          .WithTcpServer(config.Endpoint);

            if (config.CertFileCA != "")
            {
                var caCert     = X509Certificate.CreateFromCertFile(Path.Combine(certDir, config.CertFileCA));
                var clientCert = new X509Certificate2(Path.Combine(certDir, config.CertFileClient), "");

                builder = builder
                          .WithTls(new MqttClientOptionsBuilderTlsParameters()
                {
                    UseTls       = true,
                    SslProtocol  = System.Security.Authentication.SslProtocols.Tls12,
                    Certificates = new List <X509Certificate>()
                    {
                        clientCert,
                        caCert
                    },
                    IgnoreCertificateRevocationErrors = config.IgnoreCertificateRevocationErrors,
                    IgnoreCertificateChainErrors      = config.IgnoreCertificateChainErrors,
                    AllowUntrustedCertificates        = config.AllowUntrustedCertificates,
                });
            }

            return(builder
                   .WithCleanSession()
                   .Build());
        }
Beispiel #2
0
        public static async Task MakeMethodPubTask(MqttConfig config, ModuleInitInfo info, string certDir, Func <bool> shutdown)
        {
            var    mqttOptions = MakeMqttOptions(certDir, config, "MethodPub");
            var    methodPub   = config.MethodPublish !;
            string topic       = (string.IsNullOrEmpty(config.TopicRoot) ? "" : config.TopicRoot + "/") + methodPub.Topic;

            Connection clientFAST = await EnsureConnectOrThrow(info, null);

            Timestamp t = Time.GetNextNormalizedTimestamp(methodPub.PublishInterval, methodPub.PublishOffset);
            await Time.WaitUntil(t, abort : shutdown);

            IMqttClient?clientMQTT = null;

            while (!shutdown())
            {
                clientFAST = await EnsureConnectOrThrow(info, clientFAST);

                DataValue value = DataValue.Empty;

                try {
                    value = await clientFAST.CallMethod(methodPub.ModuleID, methodPub.MethodName);
                }
                catch (Exception exp) {
                    Exception e = exp.GetBaseException() ?? exp;
                    Console.Error.WriteLine($"Failed to call method {methodPub.MethodName}: {e.Message}");
                }

                if (value.NonEmpty)
                {
                    clientMQTT = await EnsureConnect(mqttOptions, clientMQTT);

                    if (clientMQTT != null)
                    {
                        string payload = value.JSON;

                        var messages = MakeMessages(payload, topic, config.MaxPayloadSize);

                        try {
                            await clientMQTT.PublishAsync(messages);

                            if (methodPub.PrintPayload)
                            {
                                Console.Out.WriteLine($"PUB: {topic}: {payload}");
                            }
                        }
                        catch (Exception exp) {
                            Exception e = exp.GetBaseException() ?? exp;
                            Console.Error.WriteLine($"Publish failed for topic {topic}: {e.Message}");
                        }
                    }
                }

                t = Time.GetNextNormalizedTimestamp(methodPub.PublishInterval, methodPub.PublishOffset);
                await Time.WaitUntil(t, abort : shutdown);
            }

            await clientFAST.Close();

            Close(clientMQTT);
        }
Beispiel #3
0
        public static async Task MakeVarPubTask(MqttConfig config, ModuleInitInfo info, string certDir, Func <bool> shutdown)
        {
            var    mqttOptions   = MakeMqttOptions(certDir, config, "VarPub");
            var    varPub        = config.VarPublish !;
            string topic         = (string.IsNullOrEmpty(config.TopicRoot) ? "" : config.TopicRoot + "/") + varPub.Topic;
            string topicRegister = varPub.TopicRegistration.Trim() == "" ? "" : (string.IsNullOrEmpty(config.TopicRoot) ? "" : config.TopicRoot + "/") + varPub.TopicRegistration;

            Timestamp t = Time.GetNextNormalizedTimestamp(varPub.PublishInterval, varPub.PublishOffset);
            await Time.WaitUntil(t, abort : shutdown);

            ObjectRef objRoot = ObjectRef.Make(varPub.ModuleID, varPub.RootObject);

            RegCache reg = new RegCache(varPub, topicRegister);

            Connection clientFAST = await EnsureConnectOrThrow(info, null);

            IMqttClient?clientMQTT = null;

            while (!shutdown())
            {
                clientFAST = await EnsureConnectOrThrow(info, clientFAST);

                string Now = Timestamp.Now.ToString();

                VariableValues values = Filter(await clientFAST.ReadAllVariablesOfObjectTree(objRoot), varPub);

                clientMQTT = await EnsureConnect(mqttOptions, clientMQTT);

                if (clientMQTT != null)
                {
                    await reg.Register(clientMQTT, values);

                    while (values.Count > 0)
                    {
                        int BatchSize = Math.Min(varPub.PayloadLimit, values.Count);
                        var batch     = values.Take(BatchSize).ToArray();
                        values.RemoveRange(0, BatchSize);

                        JObject[] payload = batch.Select(vv => FromVariableValue(vv, varPub)).ToArray();

                        var wrappedPayload = new {
                            now  = Now,
                            tags = payload
                        };

                        string msg = StdJson.ObjectToString(wrappedPayload);

                        try {
                            await clientMQTT.PublishAsync(topic, msg);

                            if (varPub.PrintPayload)
                            {
                                Console.Out.WriteLine($"PUB: {topic}: {msg}");
                            }
                        }
                        catch (Exception exp) {
                            Exception e = exp.GetBaseException() ?? exp;
                            Console.Error.WriteLine($"Publish failed for topic {topic}: {e.Message}");
                            break;
                        }
                    }
                }

                t = Time.GetNextNormalizedTimestamp(varPub.PublishInterval, varPub.PublishOffset);
                await Time.WaitUntil(t, abort : shutdown);
            }

            await clientFAST.Close();

            Close(clientMQTT);
        }
Beispiel #4
0
        public static async Task MakeConfigRecTask(MqttConfig config, ModuleInitInfo info, string certDir, Func <bool> shutdown)
        {
            SynchronizationContext theSyncContext = SynchronizationContext.Current !;

            var    mqttOptions = MakeMqttOptions(certDir, config, "ConfigRec");
            var    configRec   = config.ConfigReceive !;
            string topic       = (string.IsNullOrEmpty(config.TopicRoot) ? "" : config.TopicRoot + "/") + configRec.Topic;

            Connection clientFAST = await EnsureConnectOrThrow(info, null);

            while (!shutdown())
            {
                IMqttClient?clientMQTT = await EnsureConnect(mqttOptions, null);;

                if (clientMQTT == null)
                {
                    Console.WriteLine("Can not connect to MQTT broker");
                    await Task.Delay(5000);

                    continue;
                }

                clientFAST = await EnsureConnectOrThrow(info, clientFAST);

                var reader = new LargePayloadReader(configRec.MaxBuckets);

                clientMQTT.UseApplicationMessageReceivedHandler((arg) => {
                    var promise = new TaskCompletionSource <bool>();
                    theSyncContext !.Post(_ => {
                        Task task = OnReceivedConfigWriteRequest(clientMQTT, reader, configRec.ModuleID, topic, clientFAST, arg);
                        task.ContinueWith(completedTask => promise.CompleteFromTask(completedTask));
                    }, null);
                    return(promise.Task);
                });

                var topics = GetTopicsToSubscribe(topic, bucktesCount: configRec.MaxBuckets);

                foreach (var top in topics)
                {
                    Console.WriteLine($"Subscribing to topic {top.Topic}");
                    await clientMQTT.SubscribeAsync(top);
                }

                while (!shutdown())
                {
                    try {
                        await clientMQTT.PingAsync(CancellationToken.None);
                    }
                    catch (Exception exp) {
                        Exception e = exp.GetBaseException() ?? exp;
                        Console.Error.WriteLine($"MakeConfigRecTask: Connection broken during Ping. Trying to reconnect. Err: {e.Message}");
                        break;
                    }

                    try {
                        clientFAST = await EnsureConnectOrThrow(info, clientFAST);
                    }
                    catch (Exception) {
                        Console.Error.WriteLine("Connection to FAST core broken. Trying to reconnect...");
                        break;
                    }

                    await Time.WaitUntil(Timestamp.Now + Duration.FromSeconds(6), abort : shutdown);
                }

                await CloseIntern(clientMQTT);
            }
        }
Beispiel #5
0
        public static async Task MakeConfigPubTask(MqttConfig config, ModuleInitInfo info, string certDir, Func <bool> shutdown)
        {
            var    mqttOptions = MakeMqttOptions(certDir, config, "ConfigPub");
            var    configPub   = config.ConfigPublish !;
            string topic       = (string.IsNullOrEmpty(config.TopicRoot) ? "" : config.TopicRoot + "/") + configPub.Topic;

            bool configChanged = false;

            Action onConfigChanged = () => {
                Console.WriteLine("onConfigChanged called");
                configChanged = true;
            };

            Connection clientFAST = await EnsureConnectOrThrow(info, null, onConfigChanged, configPub.ModuleID);

            Func <bool> abortWait = () => {
                return(configChanged || shutdown());
            };

            Timestamp t = Time.GetNextNormalizedTimestamp(configPub.PublishInterval, configPub.PublishOffset);
            await Time.WaitUntil(t, abort : abortWait);

            configChanged = false;

            IMqttClient?clientMQTT = null;

            while (!shutdown())
            {
                clientFAST = await EnsureConnectOrThrow(info, clientFAST, onConfigChanged, configPub.ModuleID);

                DataValue value = await clientFAST.CallMethod(configPub.ModuleID, "GetConfigString");

                clientMQTT = await EnsureConnect(mqttOptions, clientMQTT);

                if (clientMQTT != null)
                {
                    string payload = value.GetString() ?? "";

                    var messages = MakeMessages(payload, topic, config.MaxPayloadSize);

                    try {
                        await clientMQTT.PublishAsync(messages);

                        if (configPub.PrintPayload)
                        {
                            Console.Out.WriteLine($"PUB: {topic}: {payload}");
                        }
                    }
                    catch (Exception exp) {
                        Exception e = exp.GetBaseException() ?? exp;
                        Console.Error.WriteLine($"Publish failed for topic {topic}: {e.Message}");
                    }
                }

                t = Time.GetNextNormalizedTimestamp(configPub.PublishInterval, configPub.PublishOffset);
                await Time.WaitUntil(t, abort : abortWait);

                configChanged = false;
            }

            await clientFAST.Close();

            Close(clientMQTT);
        }
Beispiel #6
0
        public static async Task MakeVarRecTask(MqttConfig config, ModuleInitInfo info, string certDir, Func <bool> shutdown)
        {
            SynchronizationContext theSyncContext = SynchronizationContext.Current !;

            var    mqttOptions = MakeMqttOptions(certDir, config, "VarRec");
            var    varRec      = config.VarReceive !;
            string topic       = (string.IsNullOrEmpty(config.TopicRoot) ? "" : config.TopicRoot + "/") + varRec.Topic;

            bool configChanged = false;

            Action onConfigChanged = () => {
                Console.WriteLine("MakeVarRecTask: onConfigChanged called");
                configChanged = true;
            };

            Connection clientFAST = await EnsureConnectOrThrow(info, null, onConfigChanged, varRec.ModuleID);

            while (!shutdown())
            {
                IMqttClient?clientMQTT = await EnsureConnect(mqttOptions, null);;

                if (clientMQTT == null)
                {
                    Console.WriteLine("Can not connect to MQTT broker");
                    await Task.Delay(5000);

                    continue;
                }

                clientFAST = await EnsureConnectOrThrow(info, clientFAST, onConfigChanged, varRec.ModuleID);

                List <ObjectInfo> objs = await clientFAST.GetAllObjects(varRec.ModuleID);

                ObjectInfo[] writableObjs = objs.Where(obj => obj.Variables.Any(v => v.Writable)).ToArray();

                MqttTopicFilter[] topics = writableObjs.Select(obj => new MqttTopicFilter()
                {
                    QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
                    Topic = $"{topic}/{obj.ID.LocalObjectID}"
                }).ToArray();

                clientMQTT.UseApplicationMessageReceivedHandler((arg) => {
                    var promise = new TaskCompletionSource <bool>();
                    theSyncContext !.Post(_ => {
                        Task task = OnReceivedVarWriteRequest(varRec, clientFAST, arg);
                        task.ContinueWith(completedTask => promise.CompleteFromTask(completedTask));
                    }, null);
                    return(promise.Task);
                });

                foreach (var top in topics)
                {
                    Console.WriteLine($"Subscribing to topic {top.Topic}");
                    await clientMQTT.SubscribeAsync(top);
                }

                while (!configChanged && !shutdown())
                {
                    try {
                        await clientMQTT.PingAsync(CancellationToken.None);
                    }
                    catch (Exception exp) {
                        Exception e = exp.GetBaseException() ?? exp;
                        Console.Error.WriteLine($"MakeVarRecTask: Connection broken during Ping. Trying to reconnect. Err: {e.Message}");
                        break;
                    }

                    try {
                        clientFAST = await EnsureConnectOrThrow(info, clientFAST, onConfigChanged, varRec.ModuleID);
                    }
                    catch (Exception) {
                        Console.Error.WriteLine("Connection to FAST core broken. Trying to reconnect...");
                        break;
                    }

                    await Time.WaitUntil(Timestamp.Now + Duration.FromSeconds(6), abort : () => configChanged || shutdown());
                }

                configChanged = false;

                await CloseIntern(clientMQTT);
            }
        }