/trunk/WingMan/Communication/MQTTClient.cs |
@@ -1,13 +1,9 @@ |
using System; |
using System.Collections.Generic; |
using System.IO; |
using System.Linq; |
using System.Net; |
using System.Runtime.Remoting.Messaging; |
using System.Text; |
using System.Threading.Tasks; |
using System.Windows.Forms; |
using System.Xml.Serialization; |
using MQTTnet; |
using MQTTnet.Client; |
using MQTTnet.Extensions.ManagedClient; |
@@ -16,49 +12,32 @@ |
{ |
public class MQTTClient : IDisposable |
{ |
private WingManForm WingManForm { get; set; } |
private IManagedMqttClient Client { get; set; } |
public bool ClientRunning { get; set; } |
|
public string Nick { get; set; } |
|
public MQTTClient() |
{ |
Client = new MqttFactory().CreateManagedMqttClient(); |
} |
|
public MQTTClient(WingManForm wingManForm) : this() |
public async Task Start(IPAddress ipAddress, int port) |
{ |
WingManForm = wingManForm; |
} |
|
public async Task Start(IPAddress ipAddress, int port, string nick) |
{ |
Nick = nick; |
|
var clientOptions = new MqttClientOptionsBuilder() |
.WithTcpServer(ipAddress.ToString(), port); |
|
// Setup and start a managed MQTT client. |
var options = new ManagedMqttClientOptionsBuilder() |
.WithAutoReconnectDelay(TimeSpan.FromSeconds(5)) |
.WithClientOptions(clientOptions.Build()) |
.WithClientOptions(new MqttClientOptionsBuilder() |
.WithTcpServer(ipAddress.ToString(), port) |
.WithTls().Build()) |
.Build(); |
|
BindHandlers(); |
|
await Client.SubscribeAsync( |
new TopicFilterBuilder() |
.WithTopic("lobby") |
.WithTopic("exchange") |
.Build() |
); |
|
await Client.SubscribeAsync( |
new TopicFilterBuilder() |
.WithTopic("exchange") |
.Build() |
); |
|
await Client.StartAsync(options); |
|
ClientRunning = true; |
@@ -66,52 +45,14 @@ |
|
private void ClientOnApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs e) |
{ |
if (e.ApplicationMessage.Topic == "lobby") |
{ |
using (var memoryStream = new MemoryStream(e.ApplicationMessage.Payload)) |
{ |
memoryStream.Position = 0L; |
|
var lobbyMessage = (LobbyMessage)LobbyMessage.XmlSerializer.Deserialize(memoryStream); |
|
UpdateLobbyMessage(lobbyMessage.Nick, lobbyMessage.Message); |
} |
return; |
} |
} |
|
private void ClientOnConnected(object sender, MqttClientConnectedEventArgs e) |
{ |
LogActivity(Properties.Strings.Client_connected); |
} |
|
private void ClientOnDisconnected(object sender, MqttClientDisconnectedEventArgs e) |
{ |
LogActivity(Properties.Strings.Client_disconnected, e.Exception.Message); |
} |
|
private void ClientOnConnectingFailed(object sender, MqttManagedProcessFailedEventArgs e) |
{ |
LogActivity(Properties.Strings.Client_connection_failed, e.Exception.Message); |
} |
|
private void UpdateLobbyMessage(string client, string message) |
{ |
WingManForm.LobbyTextBox.Invoke((MethodInvoker)delegate |
{ |
WingManForm.LobbyTextBox.AppendText($"{client} : {message}" + Environment.NewLine); |
}); |
} |
|
private void LogActivity(params string[] messages) |
{ |
WingManForm.ActivityTextBox.Invoke((MethodInvoker) delegate |
{ |
WingManForm.ActivityTextBox.Text = |
string.Join(" : ", messages) + Environment.NewLine + WingManForm.ActivityTextBox.Text; |
}); |
} |
|
public async Task Stop() |
{ |
UnbindHandlers(); |
@@ -133,8 +74,6 @@ |
public void BindHandlers() |
{ |
Client.Connected += ClientOnConnected; |
Client.Disconnected += ClientOnDisconnected; |
Client.ConnectingFailed += ClientOnConnectingFailed; |
Client.ApplicationMessageReceived += ClientOnApplicationMessageReceived; |
} |
|
@@ -141,33 +80,7 @@ |
public void UnbindHandlers() |
{ |
Client.Connected -= ClientOnConnected; |
Client.Disconnected -= ClientOnDisconnected; |
Client.ConnectingFailed -= ClientOnConnectingFailed; |
Client.ApplicationMessageReceived -= ClientOnApplicationMessageReceived; |
} |
|
public async Task BroadcastLobbyMessage(string text) |
{ |
using (var memoryStream = new MemoryStream()) |
{ |
LobbyMessage.XmlSerializer.Serialize(memoryStream, new LobbyMessage() |
{ |
Message = text, |
Nick = Nick |
}); |
|
memoryStream.Position = 0L; |
|
await Client.PublishAsync(new ManagedMqttApplicationMessage |
{ |
ApplicationMessage = new MqttApplicationMessage |
{ |
Payload = memoryStream.ToArray(), |
Topic = "lobby" |
} |
}); |
|
} |
} |
} |
} |
/trunk/WingMan/Communication/MQTTServer.cs |
@@ -1,11 +1,9 @@ |
using System; |
using System.Collections.Generic; |
using System.IO; |
using System.Linq; |
using System.Net; |
using System.Text; |
using System.Threading.Tasks; |
using System.Windows.Forms; |
using MQTTnet; |
using MQTTnet.Server; |
|
@@ -13,10 +11,8 @@ |
{ |
public class MQTTServer |
{ |
private WingManForm WingManForm { get; set; } |
private IMqttServer Server { get; set; } |
public bool ServerRunning { get; set; } |
public string Nick { get; set; } |
|
public MQTTServer() |
{ |
@@ -23,147 +19,22 @@ |
Server = new MqttFactory().CreateMqttServer(); |
} |
|
public MQTTServer(WingManForm wingManForm) : this() |
{ |
WingManForm = wingManForm; |
} |
|
public async Task Stop() |
{ |
UnbindHandlers(); |
|
await Server.StopAsync().ConfigureAwait(false); |
|
ServerRunning = false; |
} |
|
public async Task Start(IPAddress ipAddress, int port, string nick) |
public async Task Start(IPAddress ipAddress, int port) |
{ |
Nick = nick; |
|
var optionsBuilder = new MqttServerOptionsBuilder() |
.WithDefaultEndpointBoundIPAddress(ipAddress) |
.WithSubscriptionInterceptor(MQTTSubscriptionIntercept) |
.WithDefaultEndpointPort(port); |
|
BindHandlers(); |
|
await Server.StartAsync(optionsBuilder.Build()).ConfigureAwait(false); |
|
ServerRunning = true; |
} |
|
private void MQTTSubscriptionIntercept(MqttSubscriptionInterceptorContext context) |
{ |
if (context.TopicFilter.Topic != "lobby" && |
context.TopicFilter.Topic != "exchange") |
{ |
context.AcceptSubscription = false; |
context.CloseConnection = true; |
return; |
} |
|
context.AcceptSubscription = true; |
context.CloseConnection = false; |
} |
|
private void ServerOnClientUnsubscribedTopic(object sender, MqttClientUnsubscribedTopicEventArgs e) |
{ |
LogActivity(Properties.Strings.Client_unsubscribed_from_topic, e.ClientId, e.TopicFilter); |
} |
|
private void ServerOnClientSubscribedTopic(object sender, MqttClientSubscribedTopicEventArgs e) |
{ |
LogActivity(Properties.Strings.Client_subscribed_to_topic, e.ClientId, e.TopicFilter.Topic); |
} |
|
private void ServerOnClientDisconnected(object sender, MqttClientDisconnectedEventArgs e) |
{ |
LogActivity(Properties.Strings.Client_disconnected, e.ClientId); |
} |
|
private void ServerOnClientConnected(object sender, MqttClientConnectedEventArgs e) |
{ |
LogActivity(Properties.Strings.Client_connected, e.ClientId); |
} |
|
private void ServerOnStopped(object sender, EventArgs e) |
{ |
LogActivity(Properties.Strings.Server_stopped); |
} |
|
private void ServerOnStarted(object sender, EventArgs e) |
{ |
LogActivity(Properties.Strings.Server_started); |
} |
|
private void BindHandlers() |
{ |
Server.Started += ServerOnStarted; |
Server.Stopped += ServerOnStopped; |
Server.ClientConnected += ServerOnClientConnected; |
Server.ClientDisconnected += ServerOnClientDisconnected; |
Server.ClientSubscribedTopic += ServerOnClientSubscribedTopic; |
Server.ClientUnsubscribedTopic += ServerOnClientUnsubscribedTopic; |
Server.ApplicationMessageReceived += ServerOnApplicationMessageReceived; |
} |
|
private void ServerOnApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs e) |
{ |
using (var memoryStream = new MemoryStream(e.ApplicationMessage.Payload)) |
{ |
memoryStream.Position = 0L; |
|
var lobbyMessage = (LobbyMessage)LobbyMessage.XmlSerializer.Deserialize(memoryStream); |
|
UpdateLobbyMessage(lobbyMessage.Nick, lobbyMessage.Message); |
} |
} |
|
private void UnbindHandlers() |
{ |
Server.Started -= ServerOnStarted; |
Server.Stopped -= ServerOnStopped; |
Server.ClientConnected -= ServerOnClientConnected; |
Server.ClientDisconnected -= ServerOnClientDisconnected; |
Server.ClientSubscribedTopic -= ServerOnClientSubscribedTopic; |
Server.ClientUnsubscribedTopic -= ServerOnClientUnsubscribedTopic; |
Server.ApplicationMessageReceived -= ServerOnApplicationMessageReceived; |
} |
|
private void UpdateLobbyMessage(string client, string message) |
{ |
WingManForm.LobbyTextBox.Invoke((MethodInvoker)delegate |
{ |
WingManForm.LobbyTextBox.AppendText($"{client} : {message}" + Environment.NewLine); |
}); |
} |
|
private void LogActivity(params string[] messages) |
{ |
WingManForm.ActivityTextBox.Invoke((MethodInvoker) delegate |
{ |
WingManForm.ActivityTextBox.Text = |
string.Join(" : ", messages) + Environment.NewLine + WingManForm.ActivityTextBox.Text; |
}); |
} |
|
public async Task BroadcastLobbyMessage(string text) |
{ |
using (var memoryStream = new MemoryStream()) |
{ |
LobbyMessage.XmlSerializer.Serialize(memoryStream, new LobbyMessage() |
{ |
Message = text, |
Nick = Nick |
}); |
|
memoryStream.Position = 0L; |
|
await Server.PublishAsync( |
new MqttApplicationMessage { Payload = memoryStream.ToArray(), Topic = "lobby" }); |
|
} |
} |
} |
} |
/trunk/WingMan/Form1.Designer.cs |
@@ -0,0 +1,375 @@ |
namespace WingMan |
{ |
partial class Form1 |
{ |
/// <summary> |
/// Required designer variable. |
/// </summary> |
private System.ComponentModel.IContainer components = null; |
|
/// <summary> |
/// Clean up any resources being used. |
/// </summary> |
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> |
protected override void Dispose(bool disposing) |
{ |
if (disposing && (components != null)) |
{ |
components.Dispose(); |
} |
base.Dispose(disposing); |
} |
|
#region Windows Form Designer generated code |
|
/// <summary> |
/// Required method for Designer support - do not modify |
/// the contents of this method with the code editor. |
/// </summary> |
private void InitializeComponent() |
{ |
this.groupBox1 = new System.Windows.Forms.GroupBox(); |
this.button2 = new System.Windows.Forms.Button(); |
this.button1 = new System.Windows.Forms.Button(); |
this.label1 = new System.Windows.Forms.Label(); |
this.textBox1 = new System.Windows.Forms.TextBox(); |
this.listBox1 = new System.Windows.Forms.ListBox(); |
this.groupBox2 = new System.Windows.Forms.GroupBox(); |
this.button5 = new System.Windows.Forms.Button(); |
this.textBox4 = new System.Windows.Forms.TextBox(); |
this.textBox3 = new System.Windows.Forms.TextBox(); |
this.groupBox3 = new System.Windows.Forms.GroupBox(); |
this.button3 = new System.Windows.Forms.Button(); |
this.button4 = new System.Windows.Forms.Button(); |
this.label2 = new System.Windows.Forms.Label(); |
this.textBox2 = new System.Windows.Forms.TextBox(); |
this.listBox2 = new System.Windows.Forms.ListBox(); |
this.groupBox4 = new System.Windows.Forms.GroupBox(); |
this.HostButton = new System.Windows.Forms.Button(); |
this.label4 = new System.Windows.Forms.Label(); |
this.ConnectButton = new System.Windows.Forms.Button(); |
this.Port = new System.Windows.Forms.TextBox(); |
this.label3 = new System.Windows.Forms.Label(); |
this.Address = new System.Windows.Forms.TextBox(); |
this.statusStrip = new System.Windows.Forms.StatusStrip(); |
this.toolStripStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); |
this.groupBox1.SuspendLayout(); |
this.groupBox2.SuspendLayout(); |
this.groupBox3.SuspendLayout(); |
this.groupBox4.SuspendLayout(); |
this.statusStrip.SuspendLayout(); |
this.SuspendLayout(); |
// |
// groupBox1 |
// |
this.groupBox1.Controls.Add(this.button2); |
this.groupBox1.Controls.Add(this.button1); |
this.groupBox1.Controls.Add(this.label1); |
this.groupBox1.Controls.Add(this.textBox1); |
this.groupBox1.Controls.Add(this.listBox1); |
this.groupBox1.Location = new System.Drawing.Point(8, 128); |
this.groupBox1.Name = "groupBox1"; |
this.groupBox1.Size = new System.Drawing.Size(256, 296); |
this.groupBox1.TabIndex = 0; |
this.groupBox1.TabStop = false; |
this.groupBox1.Text = "Wing (Them)"; |
// |
// button2 |
// |
this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat; |
this.button2.Location = new System.Drawing.Point(168, 264); |
this.button2.Name = "button2"; |
this.button2.Size = new System.Drawing.Size(75, 23); |
this.button2.TabIndex = 4; |
this.button2.Text = "Unbind"; |
this.button2.UseVisualStyleBackColor = true; |
// |
// button1 |
// |
this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat; |
this.button1.Location = new System.Drawing.Point(88, 264); |
this.button1.Name = "button1"; |
this.button1.Size = new System.Drawing.Size(75, 23); |
this.button1.TabIndex = 3; |
this.button1.Text = "Bind"; |
this.button1.UseVisualStyleBackColor = true; |
// |
// label1 |
// |
this.label1.AutoSize = true; |
this.label1.Location = new System.Drawing.Point(8, 232); |
this.label1.Name = "label1"; |
this.label1.Size = new System.Drawing.Size(54, 13); |
this.label1.TabIndex = 2; |
this.label1.Text = "Bound To"; |
// |
// textBox1 |
// |
this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; |
this.textBox1.Location = new System.Drawing.Point(72, 228); |
this.textBox1.Name = "textBox1"; |
this.textBox1.ReadOnly = true; |
this.textBox1.Size = new System.Drawing.Size(172, 20); |
this.textBox1.TabIndex = 1; |
// |
// listBox1 |
// |
this.listBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; |
this.listBox1.FormattingEnabled = true; |
this.listBox1.Location = new System.Drawing.Point(8, 16); |
this.listBox1.Name = "listBox1"; |
this.listBox1.Size = new System.Drawing.Size(240, 184); |
this.listBox1.TabIndex = 0; |
// |
// groupBox2 |
// |
this.groupBox2.Controls.Add(this.button5); |
this.groupBox2.Controls.Add(this.textBox4); |
this.groupBox2.Controls.Add(this.textBox3); |
this.groupBox2.Location = new System.Drawing.Point(272, 128); |
this.groupBox2.Name = "groupBox2"; |
this.groupBox2.Size = new System.Drawing.Size(256, 296); |
this.groupBox2.TabIndex = 1; |
this.groupBox2.TabStop = false; |
this.groupBox2.Text = "Lobby"; |
// |
// button5 |
// |
this.button5.FlatStyle = System.Windows.Forms.FlatStyle.Flat; |
this.button5.Location = new System.Drawing.Point(208, 264); |
this.button5.Name = "button5"; |
this.button5.Size = new System.Drawing.Size(40, 20); |
this.button5.TabIndex = 2; |
this.button5.UseVisualStyleBackColor = true; |
// |
// textBox4 |
// |
this.textBox4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; |
this.textBox4.Location = new System.Drawing.Point(8, 264); |
this.textBox4.Name = "textBox4"; |
this.textBox4.Size = new System.Drawing.Size(192, 20); |
this.textBox4.TabIndex = 1; |
// |
// textBox3 |
// |
this.textBox3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; |
this.textBox3.Location = new System.Drawing.Point(8, 16); |
this.textBox3.Multiline = true; |
this.textBox3.Name = "textBox3"; |
this.textBox3.ReadOnly = true; |
this.textBox3.Size = new System.Drawing.Size(240, 240); |
this.textBox3.TabIndex = 0; |
// |
// groupBox3 |
// |
this.groupBox3.Controls.Add(this.button3); |
this.groupBox3.Controls.Add(this.button4); |
this.groupBox3.Controls.Add(this.label2); |
this.groupBox3.Controls.Add(this.textBox2); |
this.groupBox3.Controls.Add(this.listBox2); |
this.groupBox3.Location = new System.Drawing.Point(536, 128); |
this.groupBox3.Name = "groupBox3"; |
this.groupBox3.Size = new System.Drawing.Size(256, 296); |
this.groupBox3.TabIndex = 2; |
this.groupBox3.TabStop = false; |
this.groupBox3.Text = "Helm (You)"; |
// |
// button3 |
// |
this.button3.FlatStyle = System.Windows.Forms.FlatStyle.Flat; |
this.button3.Location = new System.Drawing.Point(168, 264); |
this.button3.Name = "button3"; |
this.button3.Size = new System.Drawing.Size(75, 23); |
this.button3.TabIndex = 6; |
this.button3.Text = "Remove"; |
this.button3.UseVisualStyleBackColor = true; |
// |
// button4 |
// |
this.button4.FlatStyle = System.Windows.Forms.FlatStyle.Flat; |
this.button4.Location = new System.Drawing.Point(88, 264); |
this.button4.Name = "button4"; |
this.button4.Size = new System.Drawing.Size(75, 23); |
this.button4.TabIndex = 5; |
this.button4.Text = "Add"; |
this.button4.UseVisualStyleBackColor = true; |
// |
// label2 |
// |
this.label2.AutoSize = true; |
this.label2.Location = new System.Drawing.Point(24, 232); |
this.label2.Name = "label2"; |
this.label2.Size = new System.Drawing.Size(35, 13); |
this.label2.TabIndex = 4; |
this.label2.Text = "Name"; |
// |
// textBox2 |
// |
this.textBox2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; |
this.textBox2.Location = new System.Drawing.Point(72, 228); |
this.textBox2.Name = "textBox2"; |
this.textBox2.Size = new System.Drawing.Size(172, 20); |
this.textBox2.TabIndex = 3; |
// |
// listBox2 |
// |
this.listBox2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; |
this.listBox2.FormattingEnabled = true; |
this.listBox2.Location = new System.Drawing.Point(8, 16); |
this.listBox2.Name = "listBox2"; |
this.listBox2.Size = new System.Drawing.Size(240, 184); |
this.listBox2.TabIndex = 1; |
// |
// groupBox4 |
// |
this.groupBox4.Controls.Add(this.HostButton); |
this.groupBox4.Controls.Add(this.label4); |
this.groupBox4.Controls.Add(this.ConnectButton); |
this.groupBox4.Controls.Add(this.Port); |
this.groupBox4.Controls.Add(this.label3); |
this.groupBox4.Controls.Add(this.Address); |
this.groupBox4.Location = new System.Drawing.Point(16, 8); |
this.groupBox4.Name = "groupBox4"; |
this.groupBox4.Size = new System.Drawing.Size(248, 112); |
this.groupBox4.TabIndex = 3; |
this.groupBox4.TabStop = false; |
this.groupBox4.Text = "Connection"; |
// |
// HostButton |
// |
this.HostButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; |
this.HostButton.Location = new System.Drawing.Point(96, 80); |
this.HostButton.Name = "HostButton"; |
this.HostButton.Size = new System.Drawing.Size(75, 23); |
this.HostButton.TabIndex = 6; |
this.HostButton.Text = "Host"; |
this.HostButton.UseVisualStyleBackColor = true; |
this.HostButton.Click += new System.EventHandler(this.HostButtonClickAsync); |
// |
// label4 |
// |
this.label4.AutoSize = true; |
this.label4.Location = new System.Drawing.Point(24, 52); |
this.label4.Name = "label4"; |
this.label4.Size = new System.Drawing.Size(26, 13); |
this.label4.TabIndex = 3; |
this.label4.Text = "Port"; |
// |
// ConnectButton |
// |
this.ConnectButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; |
this.ConnectButton.Location = new System.Drawing.Point(16, 80); |
this.ConnectButton.Name = "ConnectButton"; |
this.ConnectButton.Size = new System.Drawing.Size(75, 23); |
this.ConnectButton.TabIndex = 5; |
this.ConnectButton.Text = "Connect"; |
this.ConnectButton.UseVisualStyleBackColor = true; |
this.ConnectButton.Click += new System.EventHandler(this.ConnectButtonClickAsync); |
// |
// Port |
// |
this.Port.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; |
this.Port.Location = new System.Drawing.Point(56, 48); |
this.Port.Name = "Port"; |
this.Port.Size = new System.Drawing.Size(60, 20); |
this.Port.TabIndex = 2; |
this.Port.Text = "43335"; |
this.Port.Click += new System.EventHandler(this.PortTextBoxClick); |
// |
// label3 |
// |
this.label3.AutoSize = true; |
this.label3.Location = new System.Drawing.Point(8, 24); |
this.label3.Name = "label3"; |
this.label3.Size = new System.Drawing.Size(45, 13); |
this.label3.TabIndex = 1; |
this.label3.Text = "Address"; |
// |
// Address |
// |
this.Address.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; |
this.Address.Location = new System.Drawing.Point(56, 20); |
this.Address.Name = "Address"; |
this.Address.Size = new System.Drawing.Size(180, 20); |
this.Address.TabIndex = 0; |
this.Address.Text = "0.0.0.0"; |
this.Address.Click += new System.EventHandler(this.AddressTextBoxClick); |
// |
// statusStrip |
// |
this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { |
this.toolStripStatusLabel}); |
this.statusStrip.Location = new System.Drawing.Point(0, 428); |
this.statusStrip.Name = "statusStrip"; |
this.statusStrip.Size = new System.Drawing.Size(800, 22); |
this.statusStrip.TabIndex = 4; |
this.statusStrip.Text = "statusStrip1"; |
// |
// toolStripStatusLabel |
// |
this.toolStripStatusLabel.Name = "toolStripStatusLabel"; |
this.toolStripStatusLabel.Size = new System.Drawing.Size(0, 17); |
// |
// Form1 |
// |
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); |
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; |
this.ClientSize = new System.Drawing.Size(800, 450); |
this.Controls.Add(this.statusStrip); |
this.Controls.Add(this.groupBox4); |
this.Controls.Add(this.groupBox3); |
this.Controls.Add(this.groupBox2); |
this.Controls.Add(this.groupBox1); |
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; |
this.MaximizeBox = false; |
this.MaximumSize = new System.Drawing.Size(816, 488); |
this.MinimizeBox = false; |
this.MinimumSize = new System.Drawing.Size(816, 488); |
this.Name = "Form1"; |
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; |
this.Text = "Form1"; |
this.groupBox1.ResumeLayout(false); |
this.groupBox1.PerformLayout(); |
this.groupBox2.ResumeLayout(false); |
this.groupBox2.PerformLayout(); |
this.groupBox3.ResumeLayout(false); |
this.groupBox3.PerformLayout(); |
this.groupBox4.ResumeLayout(false); |
this.groupBox4.PerformLayout(); |
this.statusStrip.ResumeLayout(false); |
this.statusStrip.PerformLayout(); |
this.ResumeLayout(false); |
this.PerformLayout(); |
|
} |
|
#endregion |
|
private System.Windows.Forms.GroupBox groupBox1; |
private System.Windows.Forms.GroupBox groupBox2; |
private System.Windows.Forms.GroupBox groupBox3; |
private System.Windows.Forms.ListBox listBox1; |
private System.Windows.Forms.ListBox listBox2; |
private System.Windows.Forms.Label label1; |
private System.Windows.Forms.TextBox textBox1; |
private System.Windows.Forms.TextBox textBox4; |
private System.Windows.Forms.TextBox textBox3; |
private System.Windows.Forms.Label label2; |
private System.Windows.Forms.TextBox textBox2; |
private System.Windows.Forms.Button button2; |
private System.Windows.Forms.Button button1; |
private System.Windows.Forms.Button button3; |
private System.Windows.Forms.Button button4; |
private System.Windows.Forms.Button button5; |
private System.Windows.Forms.GroupBox groupBox4; |
private System.Windows.Forms.Button HostButton; |
private System.Windows.Forms.Label label4; |
private System.Windows.Forms.Button ConnectButton; |
private System.Windows.Forms.TextBox Port; |
private System.Windows.Forms.Label label3; |
private System.Windows.Forms.TextBox Address; |
private System.Windows.Forms.StatusStrip statusStrip; |
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel; |
} |
} |
|
/trunk/WingMan/Form1.cs |
@@ -0,0 +1,176 @@ |
using System; |
using System.Collections.Generic; |
using System.ComponentModel; |
using System.Data; |
using System.Drawing; |
using System.Globalization; |
using System.Linq; |
using System.Net; |
using System.Text; |
using System.Threading; |
using System.Threading.Tasks; |
using System.Windows.Forms; |
using WingMan.Communication; |
using WingMan.Host; |
|
namespace WingMan |
{ |
public partial class Form1 : Form |
{ |
private MQTTServer MQTTServer { get; set; } = new MQTTServer(); |
|
private MQTTClient MQTTClient { get; set; } = new MQTTClient(); |
|
private SemaphoreSlim MQTTServerSemaphore {get; set;} = new SemaphoreSlim(1, 1); |
|
private SemaphoreSlim MQTTClientSemaphore { get; set; } = new SemaphoreSlim(1, 1); |
|
public Form1() |
{ |
InitializeComponent(); |
} |
|
private void AddressTextBoxClick(object sender, EventArgs e) |
{ |
Address.BackColor = Color.Empty; |
} |
|
private void PortTextBoxClick(object sender, EventArgs e) |
{ |
Port.BackColor = Color.Empty; |
} |
|
private async void HostButtonClickAsync(object sender, EventArgs e) |
{ |
// Stop the MQTT server if it is running. |
if (MQTTServer.ServerRunning) |
{ |
await StopServer(); |
toolStripStatusLabel.Text = Properties.Strings.Server_stopped; |
HostButton.BackColor = Color.Empty; |
|
ConnectButton.Enabled = true; |
return; |
} |
|
if (!ValidateAddressPort(out var ipAddress, out var port)) |
return; |
|
// Start the MQTT server. |
await StartServer(ipAddress, port); |
toolStripStatusLabel.Text = Properties.Strings.Server_started; |
HostButton.BackColor = Color.Aquamarine; |
|
ConnectButton.Enabled = false; |
} |
|
private bool ValidateAddressPort(out IPAddress address, out int port) |
{ |
address = IPAddress.Any; |
port = 0; |
|
if (string.IsNullOrEmpty(Address.Text) && |
string.IsNullOrEmpty(Port.Text)) |
{ |
Address.BackColor = Color.LightPink; |
Port.BackColor = Color.LightPink; |
return false; |
} |
|
if (!IPAddress.TryParse(Address.Text, out address)) |
{ |
Address.BackColor = Color.LightPink; |
return false; |
} |
|
if (!uint.TryParse(Port.Text, out var uPort)) |
{ |
Port.BackColor = Color.LightPink; |
return false; |
} |
|
port = (int) uPort; |
|
Address.BackColor = Color.Empty; |
Port.BackColor = Color.Empty; |
|
return true; |
} |
|
private async Task StartServer(IPAddress ipAddress, int port) |
{ |
await MQTTServerSemaphore.WaitAsync(); |
try |
{ |
await MQTTServer.Start(ipAddress, port); |
} |
finally |
{ |
MQTTServerSemaphore.Release(); |
} |
} |
|
private async Task StopServer() |
{ |
await MQTTServerSemaphore.WaitAsync(); |
try |
{ |
await MQTTServer.Stop(); |
} |
finally |
{ |
MQTTServerSemaphore.Release(); |
} |
} |
|
private async void ConnectButtonClickAsync(object sender, EventArgs e) |
{ |
if (MQTTClient.ClientRunning) |
{ |
await StopClient(); |
ConnectButton.Text = Properties.Strings.Connect; |
ConnectButton.BackColor = Color.Empty; |
|
HostButton.Enabled = true; |
return; |
} |
|
if (!ValidateAddressPort(out var ipAddress, out var port)) |
return; |
|
await StartClient(ipAddress, port); |
|
toolStripStatusLabel.Text = Properties.Strings.Client_started; |
ConnectButton.Text = Properties.Strings.Disconnect; |
ConnectButton.BackColor = Color.Aquamarine; |
|
HostButton.Enabled = false; |
} |
|
private async Task StopClient() |
{ |
await MQTTClientSemaphore.WaitAsync(); |
try |
{ |
await MQTTClient.Stop(); |
} |
finally |
{ |
MQTTClientSemaphore.Release(); |
} |
} |
|
private async Task StartClient(IPAddress ipAddress, int port) |
{ |
await MQTTClientSemaphore.WaitAsync(); |
try |
{ |
await MQTTClient.Start(ipAddress, port); |
} |
finally |
{ |
MQTTClientSemaphore.Release(); |
} |
} |
} |
} |
/trunk/WingMan/Form1.resx |
@@ -0,0 +1,123 @@ |
<?xml version="1.0" encoding="utf-8"?> |
<root> |
<!-- |
Microsoft ResX Schema |
|
Version 2.0 |
|
The primary goals of this format is to allow a simple XML format |
that is mostly human readable. The generation and parsing of the |
various data types are done through the TypeConverter classes |
associated with the data types. |
|
Example: |
|
... ado.net/XML headers & schema ... |
<resheader name="resmimetype">text/microsoft-resx</resheader> |
<resheader name="version">2.0</resheader> |
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> |
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> |
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> |
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> |
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> |
<value>[base64 mime encoded serialized .NET Framework object]</value> |
</data> |
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> |
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> |
<comment>This is a comment</comment> |
</data> |
|
There are any number of "resheader" rows that contain simple |
name/value pairs. |
|
Each data row contains a name, and value. The row also contains a |
type or mimetype. Type corresponds to a .NET class that support |
text/value conversion through the TypeConverter architecture. |
Classes that don't support this are serialized and stored with the |
mimetype set. |
|
The mimetype is used for serialized objects, and tells the |
ResXResourceReader how to depersist the object. This is currently not |
extensible. For a given mimetype the value must be set accordingly: |
|
Note - application/x-microsoft.net.object.binary.base64 is the format |
that the ResXResourceWriter will generate, however the reader can |
read any of the formats listed below. |
|
mimetype: application/x-microsoft.net.object.binary.base64 |
value : The object must be serialized with |
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter |
: and then encoded with base64 encoding. |
|
mimetype: application/x-microsoft.net.object.soap.base64 |
value : The object must be serialized with |
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter |
: and then encoded with base64 encoding. |
|
mimetype: application/x-microsoft.net.object.bytearray.base64 |
value : The object must be serialized into a byte array |
: using a System.ComponentModel.TypeConverter |
: and then encoded with base64 encoding. |
--> |
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> |
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> |
<xsd:element name="root" msdata:IsDataSet="true"> |
<xsd:complexType> |
<xsd:choice maxOccurs="unbounded"> |
<xsd:element name="metadata"> |
<xsd:complexType> |
<xsd:sequence> |
<xsd:element name="value" type="xsd:string" minOccurs="0" /> |
</xsd:sequence> |
<xsd:attribute name="name" use="required" type="xsd:string" /> |
<xsd:attribute name="type" type="xsd:string" /> |
<xsd:attribute name="mimetype" type="xsd:string" /> |
<xsd:attribute ref="xml:space" /> |
</xsd:complexType> |
</xsd:element> |
<xsd:element name="assembly"> |
<xsd:complexType> |
<xsd:attribute name="alias" type="xsd:string" /> |
<xsd:attribute name="name" type="xsd:string" /> |
</xsd:complexType> |
</xsd:element> |
<xsd:element name="data"> |
<xsd:complexType> |
<xsd:sequence> |
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> |
</xsd:sequence> |
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> |
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> |
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> |
<xsd:attribute ref="xml:space" /> |
</xsd:complexType> |
</xsd:element> |
<xsd:element name="resheader"> |
<xsd:complexType> |
<xsd:sequence> |
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
</xsd:sequence> |
<xsd:attribute name="name" type="xsd:string" use="required" /> |
</xsd:complexType> |
</xsd:element> |
</xsd:choice> |
</xsd:complexType> |
</xsd:element> |
</xsd:schema> |
<resheader name="resmimetype"> |
<value>text/microsoft-resx</value> |
</resheader> |
<resheader name="version"> |
<value>2.0</value> |
</resheader> |
<resheader name="reader"> |
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
</resheader> |
<resheader name="writer"> |
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
</resheader> |
<metadata name="statusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> |
<value>17, 17</value> |
</metadata> |
</root> |