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()); }
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); }
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); }
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); } }
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); }
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); } }