477 lines
18 KiB
C#
477 lines
18 KiB
C#
|
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
// <copyright file="Form1.cs" company="Haemmer Electronics">
|
|||
|
// Copyright (c) 2020 All rights reserved.
|
|||
|
// </copyright>
|
|||
|
// <summary>
|
|||
|
// The main form.
|
|||
|
// </summary>
|
|||
|
// --------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
namespace MQTTnet.TestApp.WinForm
|
|||
|
{
|
|||
|
using System;
|
|||
|
using System.Text;
|
|||
|
using System.Timers;
|
|||
|
using System.Windows.Forms;
|
|||
|
|
|||
|
using MQTTnet.Client.Connecting;
|
|||
|
using MQTTnet.Client.Disconnecting;
|
|||
|
using MQTTnet.Client.Options;
|
|||
|
using MQTTnet.Client.Receiving;
|
|||
|
using MQTTnet.Extensions.ManagedClient;
|
|||
|
using MQTTnet.Formatter;
|
|||
|
using MQTTnet.Protocol;
|
|||
|
using MQTTnet.Server;
|
|||
|
using Newtonsoft.Json;
|
|||
|
using Timer = System.Timers.Timer;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The main form.
|
|||
|
/// </summary>
|
|||
|
public partial class Form1 : Form
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// The managed publisher client.
|
|||
|
/// </summary>
|
|||
|
private IManagedMqttClient managedMqttClientPublisher;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The managed subscriber client.
|
|||
|
/// </summary>
|
|||
|
private IManagedMqttClient managedMqttClientSubscriber;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The MQTT server.
|
|||
|
/// </summary>
|
|||
|
private IMqttServer mqttServer;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The port.
|
|||
|
/// </summary>
|
|||
|
private string port = "1883";
|
|||
|
|
|||
|
private readonly Random random;
|
|||
|
private readonly Timer randomPublisherTimer;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Initializes a new instance of the <see cref="Form1"/> class.
|
|||
|
/// </summary>
|
|||
|
public Form1()
|
|||
|
{
|
|||
|
this.InitializeComponent();
|
|||
|
|
|||
|
var timer = new Timer
|
|||
|
{
|
|||
|
AutoReset = true, Enabled = true, Interval = 1000
|
|||
|
};
|
|||
|
|
|||
|
timer.Elapsed += this.TimerElapsed;
|
|||
|
|
|||
|
random = new Random();
|
|||
|
randomPublisherTimer = new Timer
|
|||
|
{
|
|||
|
AutoReset = true,
|
|||
|
Enabled = false,
|
|||
|
};
|
|||
|
|
|||
|
randomPublisherTimer.Elapsed += (_, __) => this.BeginInvoke((MethodInvoker)delegate
|
|||
|
{
|
|||
|
if (checkBox1.Checked)
|
|||
|
ButtonGeneratePublishedMessageClick(ButtonGeneratePublishedMessage, EventArgs.Empty);
|
|||
|
|
|||
|
ButtonPublishClick(ButtonPublish, EventArgs.Empty);
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Handles the publisher connected event.
|
|||
|
/// </summary>
|
|||
|
/// <param name="x">The MQTT client connected event args.</param>
|
|||
|
private void OnPublisherConnected(MqttClientConnectedEventArgs x)
|
|||
|
{
|
|||
|
var item = "Publisher Connected";
|
|||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Handles the publisher disconnected event.
|
|||
|
/// </summary>
|
|||
|
/// <param name="x">The MQTT client disconnected event args.</param>
|
|||
|
private void OnPublisherDisconnected(MqttClientDisconnectedEventArgs x)
|
|||
|
{
|
|||
|
var item = "Publisher Disconnected";
|
|||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Handles the subscriber connected event.
|
|||
|
/// </summary>
|
|||
|
/// <param name="x">The MQTT client connected event args.</param>
|
|||
|
private void OnSubscriberConnected(MqttClientConnectedEventArgs x)
|
|||
|
{
|
|||
|
var item = "Subscriber Connected";
|
|||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Handles the subscriber disconnected event.
|
|||
|
/// </summary>
|
|||
|
/// <param name="x">The MQTT client disconnected event args.</param>
|
|||
|
private void OnSubscriberDisconnected(MqttClientDisconnectedEventArgs x)
|
|||
|
{
|
|||
|
var item = "Subscriber Disconnected";
|
|||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the button click to generate a message.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private void ButtonGeneratePublishedMessageClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
var message = new
|
|||
|
{
|
|||
|
tag = Guid.NewGuid(),
|
|||
|
probability = random.NextDouble(),
|
|||
|
};
|
|||
|
|
|||
|
var json = JsonConvert.SerializeObject(message);
|
|||
|
this.TextBoxPublish.Text = json;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the button click to publish a message.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private async void ButtonPublishClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
((Button)sender).Enabled = false;
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
var payload = Encoding.UTF8.GetBytes(this.TextBoxPublish.Text);
|
|||
|
var message = new MqttApplicationMessageBuilder().WithTopic(this.TextBoxTopicPublished.Text.Trim()).WithPayload(payload).WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce).WithRetainFlag().Build();
|
|||
|
|
|||
|
if (this.managedMqttClientPublisher != null)
|
|||
|
{
|
|||
|
await this.managedMqttClientPublisher.PublishAsync(message);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
var item = ex.Message;
|
|||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
|||
|
}
|
|||
|
|
|||
|
((Button)sender).Enabled = true;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the button click to start the publisher.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private async void ButtonPublisherStartClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
var mqttFactory = new MqttFactory();
|
|||
|
|
|||
|
var tlsOptions = new MqttClientTlsOptions
|
|||
|
{
|
|||
|
UseTls = false, IgnoreCertificateChainErrors = true, IgnoreCertificateRevocationErrors = true, AllowUntrustedCertificates = true
|
|||
|
};
|
|||
|
|
|||
|
var options = new MqttClientOptions
|
|||
|
{
|
|||
|
ClientId = "ClientPublisher",
|
|||
|
ProtocolVersion = MqttProtocolVersion.V311,
|
|||
|
ChannelOptions = new MqttClientTcpOptions
|
|||
|
{
|
|||
|
Server = "localhost", Port = int.Parse(this.TextBoxPort.Text.Trim()), TlsOptions = tlsOptions
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
if (options.ChannelOptions == null)
|
|||
|
{
|
|||
|
throw new InvalidOperationException();
|
|||
|
}
|
|||
|
|
|||
|
options.Credentials = new MqttClientCredentials
|
|||
|
{
|
|||
|
Username = "username", Password = Encoding.UTF8.GetBytes("password")
|
|||
|
};
|
|||
|
|
|||
|
options.CleanSession = true;
|
|||
|
options.KeepAlivePeriod = TimeSpan.FromSeconds(5);
|
|||
|
this.managedMqttClientPublisher = mqttFactory.CreateManagedMqttClient();
|
|||
|
this.managedMqttClientPublisher.UseApplicationMessageReceivedHandler(this.HandleReceivedApplicationMessage);
|
|||
|
this.managedMqttClientPublisher.ConnectedHandler = new MqttClientConnectedHandlerDelegate(OnPublisherConnected);
|
|||
|
this.managedMqttClientPublisher.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(OnPublisherDisconnected);
|
|||
|
|
|||
|
await this.managedMqttClientPublisher.StartAsync(
|
|||
|
new ManagedMqttClientOptions
|
|||
|
{
|
|||
|
ClientOptions = options
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the button click to stop the publisher.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private async void ButtonPublisherStopClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (this.managedMqttClientPublisher == null)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
await this.managedMqttClientPublisher.StopAsync();
|
|||
|
this.managedMqttClientPublisher = null;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the button click to start the server.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private async void ButtonServerStartClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (this.mqttServer != null)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
var storage = new JsonServerStorage();
|
|||
|
storage.Clear();
|
|||
|
this.mqttServer = new MqttFactory().CreateMqttServer();
|
|||
|
var options = new MqttServerOptions();
|
|||
|
options.DefaultEndpointOptions.Port = int.Parse(this.TextBoxPort.Text);
|
|||
|
options.Storage = storage;
|
|||
|
options.EnablePersistentSessions = true;
|
|||
|
options.ConnectionValidator = new MqttServerConnectionValidatorDelegate(
|
|||
|
c =>
|
|||
|
{
|
|||
|
if (c.ClientId.Length < 10)
|
|||
|
{
|
|||
|
c.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (c.Username != "username")
|
|||
|
{
|
|||
|
c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (c.Password != "password")
|
|||
|
{
|
|||
|
c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
c.ReasonCode = MqttConnectReasonCode.Success;
|
|||
|
});
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
await this.mqttServer.StartAsync(options);
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
var item = ex.Message;
|
|||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
|||
|
|
|||
|
await this.mqttServer.StopAsync();
|
|||
|
this.mqttServer = null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the button click to stop the server.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private async void ButtonServerStopClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (this.mqttServer == null)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
await this.mqttServer.StopAsync();
|
|||
|
this.mqttServer = null;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the button click to subscribe to a certain topic.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private async void ButtonSubscribeClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
var topicFilter = new MqttTopicFilter { Topic = this.TextBoxTopicSubscribed.Text.Trim() };
|
|||
|
await this.managedMqttClientSubscriber.SubscribeAsync(topicFilter);
|
|||
|
var item = "Topic " + this.TextBoxTopicSubscribed.Text.Trim() + " is subscribed";
|
|||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the button click to start the subscriber.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private async void ButtonSubscriberStartClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
var mqttFactory = new MqttFactory();
|
|||
|
|
|||
|
var tlsOptions = new MqttClientTlsOptions
|
|||
|
{
|
|||
|
UseTls = false, IgnoreCertificateChainErrors = true, IgnoreCertificateRevocationErrors = true, AllowUntrustedCertificates = true
|
|||
|
};
|
|||
|
|
|||
|
var options = new MqttClientOptions
|
|||
|
{
|
|||
|
ClientId = "ClientSubscriber",
|
|||
|
ProtocolVersion = MqttProtocolVersion.V311,
|
|||
|
ChannelOptions = new MqttClientTcpOptions
|
|||
|
{
|
|||
|
Server = "localhost", Port = int.Parse(this.TextBoxPort.Text.Trim()), TlsOptions = tlsOptions
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
if (options.ChannelOptions == null)
|
|||
|
{
|
|||
|
throw new InvalidOperationException();
|
|||
|
}
|
|||
|
|
|||
|
options.Credentials = new MqttClientCredentials
|
|||
|
{
|
|||
|
Username = "username",
|
|||
|
Password = Encoding.UTF8.GetBytes("password")
|
|||
|
};
|
|||
|
|
|||
|
options.CleanSession = true;
|
|||
|
options.KeepAlivePeriod = TimeSpan.FromSeconds(5);
|
|||
|
|
|||
|
this.managedMqttClientSubscriber = mqttFactory.CreateManagedMqttClient();
|
|||
|
this.managedMqttClientSubscriber.ConnectedHandler = new MqttClientConnectedHandlerDelegate(OnSubscriberConnected);
|
|||
|
this.managedMqttClientSubscriber.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(OnSubscriberDisconnected);
|
|||
|
this.managedMqttClientSubscriber.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(this.OnSubscriberMessageReceived);
|
|||
|
|
|||
|
await this.managedMqttClientSubscriber.StartAsync(
|
|||
|
new ManagedMqttClientOptions
|
|||
|
{
|
|||
|
ClientOptions = options
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the button click to stop the subscriber.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private async void ButtonSubscriberStopClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (this.managedMqttClientSubscriber == null)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
await this.managedMqttClientSubscriber.StopAsync();
|
|||
|
this.managedMqttClientSubscriber = null;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Handles the received application message event.
|
|||
|
/// </summary>
|
|||
|
/// <param name="x">The MQTT application message received event args.</param>
|
|||
|
private void HandleReceivedApplicationMessage(MqttApplicationMessageReceivedEventArgs x)
|
|||
|
{
|
|||
|
var item = $"Timestamp: {DateTime.Now:O} | Topic: {x.ApplicationMessage.Topic} | Payload: {x.ApplicationMessage.ConvertPayloadToString()} | QoS: {x.ApplicationMessage.QualityOfServiceLevel}";
|
|||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Handles the received subscriber message event.
|
|||
|
/// </summary>
|
|||
|
/// <param name="x">The MQTT application message received event args.</param>
|
|||
|
private void OnSubscriberMessageReceived(MqttApplicationMessageReceivedEventArgs x)
|
|||
|
{
|
|||
|
var item = $"Timestamp: {DateTime.Now:O} | Topic: {x.ApplicationMessage.Topic} | Payload: {x.ApplicationMessage.ConvertPayloadToString()} | QoS: {x.ApplicationMessage.QualityOfServiceLevel}";
|
|||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the text changes in the text box.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private void TextBoxPortTextChanged(object sender, EventArgs e)
|
|||
|
{
|
|||
|
// ReSharper disable once StyleCop.SA1126
|
|||
|
if (int.TryParse(this.TextBoxPort.Text, out _))
|
|||
|
{
|
|||
|
this.port = this.TextBoxPort.Text.Trim();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
this.TextBoxPort.Text = this.port;
|
|||
|
this.TextBoxPort.SelectionStart = this.TextBoxPort.Text.Length;
|
|||
|
this.TextBoxPort.SelectionLength = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// The method that handles the timer events.
|
|||
|
/// </summary>
|
|||
|
/// <param name="sender">The sender.</param>
|
|||
|
/// <param name="e">The event args.</param>
|
|||
|
private void TimerElapsed(object sender, ElapsedEventArgs e)
|
|||
|
{
|
|||
|
this.BeginInvoke(
|
|||
|
(MethodInvoker)delegate
|
|||
|
{
|
|||
|
// Server
|
|||
|
this.TextBoxPort.Enabled = this.mqttServer == null;
|
|||
|
this.ButtonServerStart.Enabled = this.mqttServer == null;
|
|||
|
this.ButtonServerStop.Enabled = this.mqttServer != null;
|
|||
|
|
|||
|
// Publisher
|
|||
|
this.ButtonPublisherStart.Enabled = this.managedMqttClientPublisher == null;
|
|||
|
this.ButtonPublisherStop.Enabled = this.managedMqttClientPublisher != null;
|
|||
|
|
|||
|
// Auto Publisher
|
|||
|
this.ButtonAutoPublisherStart.Enabled = !this.randomPublisherTimer.Enabled;
|
|||
|
this.ButtonAutoPublisherStop.Enabled = this.randomPublisherTimer.Enabled;
|
|||
|
|
|||
|
// Subscriber
|
|||
|
this.ButtonSubscriberStart.Enabled = this.managedMqttClientSubscriber == null;
|
|||
|
this.ButtonSubscriberStop.Enabled = this.managedMqttClientSubscriber != null;
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
private void trackBar1_Scroll(object sender, EventArgs e)
|
|||
|
{
|
|||
|
this.label8.Text = $"{this.trackBar1.Value:N0} ms";
|
|||
|
this.randomPublisherTimer.Interval = this.trackBar1.Value;
|
|||
|
}
|
|||
|
|
|||
|
private void ButtonAutoPublisherStartClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
((Button)sender).Enabled = false;
|
|||
|
this.randomPublisherTimer.Start();
|
|||
|
((Button)sender).Enabled = true;
|
|||
|
}
|
|||
|
|
|||
|
private void ButtonAutoPublisherStopClick(object sender, EventArgs e)
|
|||
|
{
|
|||
|
((Button)sender).Enabled = false;
|
|||
|
this.randomPublisherTimer.Stop();
|
|||
|
((Button)sender).Enabled = true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|