/// <summary> /// Adds the disconnected handler and the reconnect functionality to the client. /// </summary> /// <param name="options">The configuration option.</param> private void AddDisconnectedHandler(SparkplugApplicationOptions options) { this.Client.UseDisconnectedHandler( async e => { // Todo: Use the metrics correctly. //// Set all states to unknown as we are disconnected //foreach (var nodeState in this.NodeStatesPayloadA) //{ // var value = this.NodeStatesPayloadA[nodeState.Key]; // value.ConnectionStatus = SparkplugConnectionStatus.Unknown; // this.NodeStatesPayloadA[nodeState.Key] = value; //} //// Set all states to unknown as we are disconnected //foreach (var nodeState in this.NodeStatesPayloadB) //{ // var value = this.NodeStatesPayloadB[nodeState.Key]; // value.ConnectionStatus = SparkplugConnectionStatus.Unknown; // this.NodeStatesPayloadB[nodeState.Key] = value; //} // Wait until the disconnect interval is reached await Task.Delay(options.ReconnectInterval); // Connect, subscribe to incoming messages and send a state message await this.ConnectInternal(options); await this.SubscribeInternal(); await this.PublishInternal(options); }); }
/// <summary> /// Publishes data to the MQTT broker. /// </summary> /// <param name="options">The configuration option.</param> /// <returns>A <see cref="Task"/> representing any asynchronous operation.</returns> private async Task PublishInternal(SparkplugApplicationOptions options) { // Only send state messages for the primary application if (options.IsPrimaryApplication) { options.CancellationToken ??= CancellationToken.None; await this.Client.PublishAsync(this.applicationOnlineMessage, options.CancellationToken.Value); } }
/// <summary> /// Loads the messages used by the the Sparkplug application. /// </summary> /// <param name="options">The configuration option.</param> private void LoadMessages(SparkplugApplicationOptions options) { this.willMessage = this.MessageGenerator.GetSparkplugStateMessage( this.NameSpace, options.ScadaHostIdentifier, false); this.applicationOnlineMessage = this.MessageGenerator.GetSparkplugStateMessage( this.NameSpace, options.ScadaHostIdentifier, true); }
/// <summary> /// Connects the Sparkplug application to the MQTT broker. /// </summary> /// <param name="options">The configuration option.</param> /// <returns>A <see cref="Task"/> representing any asynchronous operation.</returns> private async Task ConnectInternal(SparkplugApplicationOptions options) { options.CancellationToken ??= CancellationToken.None; var builder = new MqttClientOptionsBuilder() .WithClientId(options.ClientId) .WithCredentials(options.UserName, options.Password) .WithCleanSession(false) .WithProtocolVersion(MqttProtocolVersion.V311); if (options.UseTls) { builder.WithTls(); } if (options.WebSocketParameters is null) { builder.WithTcpServer(options.BrokerAddress, options.Port); } else { builder.WithWebSocketServer(options.BrokerAddress, options.WebSocketParameters); } if (options.ProxyOptions != null) { builder.WithProxy( options.ProxyOptions.Address, options.ProxyOptions.Username, options.ProxyOptions.Password, options.ProxyOptions.Domain, options.ProxyOptions.BypassOnLocal); } if (this.willMessage != null && options.IsPrimaryApplication) { builder.WithWillMessage(this.willMessage); } this.ClientOptions = builder.Build(); await this.Client.ConnectAsync(this.ClientOptions, options.CancellationToken.Value); }
/// <summary> /// Starts the Sparkplug application. /// </summary> /// <param name="options">The configuration option.</param> /// <returns>A <see cref="Task"/> representing any asynchronous operation.</returns> public async Task Start(SparkplugApplicationOptions options) { // Clear states this.NodeStatesPayloadA.Clear(); this.NodeStatesPayloadB.Clear(); // Load messages this.LoadMessages(options); // Add handlers this.AddDisconnectedHandler(options); this.AddMessageReceivedHandler(); // Connect, subscribe to incoming messages and send a state message await this.ConnectInternal(options); await this.SubscribeInternal(); await this.PublishInternal(options); }