In this topic I will be sending data from a C# client using a highly volatile protocol to any other client that might be interested in this data. This concept is also called pub/sub or the publish subsrcibe pattern. We need a few components to make this possible:
- C# client
- A messaging protocol (used by the client software to either publish or subscribe)
- A broker (for managing the pub/sub data flows). For more information goto this topic
The C# client
C♯ is one of the programming languages designed for the Common Language Infrastructure. C# is built on the syntax and semantics of C++, allowing C programmers to take advantage of .NET and the common language runtime. For more information: wikipedia.
The protocol
MQTT is a machine-to-machine (M2M)/”Internet of Things” connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is required and/or network bandwidth is at a premium. For more information: http://mqtt.org/.
What is happening?
This is sample client based upon the .NET class M2MQTT. It is a simple client that connects to a Mosquitto broker, subscribes to a topic and published a text to the same topic.
Connecting to the broker
Publishing the text
And hereby the code:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Net; using System.Windows.Forms; using uPLibrary.Networking.M2Mqtt; using uPLibrary.Networking.M2Mqtt.Messages; namespace MQTTHandler { public partial class MainForm : Form { MqttClient clientSub; delegate void SetTextCallback(string text); public MainForm() { InitializeComponent(); } private void MainForm_Load(object sender, EventArgs e) { try { IPAddress HostIP; HostIP = IPAddress.Parse(TextBox1.Text); clientSub = new MqttClient(HostIP); clientSub.MqttMsgPublishReceived += new MqttClient.MqttMsgPublishEventHandler(EventPublished); } catch (InvalidCastException ex) { } } private void EventPublished(Object sender,uPLibrary.Networking.M2Mqtt.Messages.MqttMsgPublishEventArgs e) { try { SetText("*** Received Message"); SetText("*** Topic: " + e.Topic); SetText("*** Message: " + System.Text.UTF8Encoding.UTF8.GetString(e.Message)); SetText(""); } catch (InvalidCastException ex) { } } private void SetText(string text) { if (this.ListBox1.InvokeRequired) { SetTextCallback d = new SetTextCallback(SetText); this.Invoke(d, new object[] { text }); } else { this.ListBox1.Items.Add(text); } } private void Button1_Click(object sender, EventArgs e) { try { clientSub.Connect(TextBox2.Text + "_sub"); ListBox1.Items.Add("* Client connected"); clientSub.Subscribe(new string[] { TextBox3.Text }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE }); ListBox1.Items.Add("** Subscribing to: " + TextBox3.Text); } catch (InvalidCastException ex) { } } private void Button2_Click(object sender, EventArgs e) { try { clientSub.Publish(TextBox3.Text, Encoding.UTF8.GetBytes(TextBox4.Text), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE); ListBox1.Items.Add("*** Publishing on: " + TextBox3.Text); } catch (InvalidCastException ex) { } } private void Button3_Click(object sender, EventArgs e) { try { clientSub.Disconnect(); ListBox1.Items.Add("* Client disconnected"); } catch (InvalidCastException ex) { } } } } }
There was one small issue: Thread-Safe Calls to Windows Forms Controls. For more information: MSDN. Basically due to subscribing to the topic, the subscription event will try to write to the listbox (used to display the log results) but from a different thread than the Windows form is running on. To solve this I used:
delegate void SetTextCallback(string text);
And this procedure to update the listbox:
private void SetText(string text)
{
if (this.ListBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.ListBox1.Items.Add(text);
}
}
Thank you very much for such a nice tutorial for understanding MQTT Protocol.