MQTT Client Library Encyclopedia – M2Mqtt

Written by Paolo Patierno

Category: MQTT MQTT Client Library

Published: July 25, 2015




Short info

M2Mqtt
Language C#
License Eclipse Public License
Website https://m2mqtt.wordpress.com
API Style Asynchronous

Description

Until October 2014, the Eclipse Paho (the umbrella project for all the main MQTT clients) didn’t have an implementation based on Microsoft technologies. It had support for a lot of different programming languages, but not for C#. For this reason, the Eclipse Foundation asked me to take my M2Mqtt library under Paho umbrella, to make its offer more complete. In this way, M2Mqtt project (who was born in the April 2013) became the official C# implementation of Eclipse Paho, and provided an MQTT client for all .Net Framework platforms (full, compact and micro) and WinRT (Windows 8.1, Windows Phone 8.1 and the future Windows 10).

Today the library is more mature and production ready. There are lots of makers using it in their hobbystic projects, and more companies are deploying it in their Internet of Things solutions up and running 247. M2Mqtt provides all the main features of the MQTT standard from all the three QoS levels and “last will and testament” to SSL/TLS support. It exposes an API that works in an asynchronous fashion even if not in the “Task based” way that the new async/await keywords (C# 5.0) need. Of course this could be a future improvement, because the project is always under development and the team (me and myself) accept all types of suggestions or contributes to it.

Features

Feature
MQTT 3.1 ok
MQTT 3.1.1 ok
LWT ok
SSL/TLS ok
Automatic Reconnect nok
Disk Persistence nok
Feature
QoS 0 ok
QoS 1 ok
QoS 2 ok
Authentication ok
Throttling nok
Offline Message Buffering nok


Usage

Installation

The M2Mqtt library is available in two different ways:

  • as source code on the official Eclipse Paho project or Github that you have to build
  • as a “cooked” Nuget package that you can simply reference from your Visual Studio project using the built-in Nuget Package Manager or the related console. (preferred way for all .Net developers)

It has no dependencies and the referenced assembly changes due to the type of project you are working on (.Net Framework, .Net Micro Framework, Windows 8.1 and so on) : Nuget manager takes care of those issues for you !

Connect

In order to use the M2Mqtt library, first of all you need to create an instance of MqttClient class (in the uPLibrary.Networking.M2Mqtt namespace).

MqttClient client = new MqttClient("broker.hivemq.com");

The simplest overload of the MqttClient class constructor needs only the MQTT broker URL as parameter without specifying the protocol (it’s TCP) and the port (the default is 1883); it can be an host name or an IP address. There are other overloads that you can use to specify:

  • A different port (not standard 1883 or 8883 for TLS/SSL connection)
  • The X509 certificate needed for a TLS/SSL connection to the broker (as we’ll see in the following sections)
  • Optional callbacks for above certificate validation

After creating an MqttClient object you need to call the Connect( ) method to connect to the broker.

byte code = client.Connect(Guid.NewGuid().ToString());

The simplest overload of this method needs only the client id that in the above example is generated as a GUID. It’s important to say that the library uses MQTT 3.1.1 specification as default so it hasn’t the 23 characters limit for the client id as in the previous MQTT 3.1 specification. The Connect( ) method is synchronous and it returns a byte that represents the response code from the broker; from the MQTT specification it’s value is 0 if the connection was accepted or a number greater than 0 identifying the reason of connection failure. During the client life you can always retrieve the client id and the connection status accessing to the ClientId and IsConnected properties. All the other overloads of the connection method allow you to specify :

  • Username and password for authentication (they are null as default, no authentication)
  • “Clean session” flag that you can set to false so that the broker will save the client session on disconnection (subscribed topics, messages for these topics delivered on reconnection). Please note that the default value is true, so the broker doesn’t save any session information about the client
  • “Keep alive period” used by the client to send the ping message as “heart beat” (the default value is 60 seconds)
  • All information related to the “last will and testament” feature like the will topic, will message, will Qos level and will retain flag (of course, they are null as default)

Connect with MQTT 3.1 or MQTT 3.1.1

By default, M2Mqtt connects to the broker using the new MQTT 3.1.1 specification but if you have an old MQTT 3.1 compliant broker you can set this version using the ProtocolVersion property of the MqttClient instance in the following way.

client.ProtocolVersion = MqttProtocolVersion.Version_3_1;

Remember to set the protocol version before calling the Connect() method.

Connect with LWT

As mentioned before, in order to use the “last will and testament” feature you can specify all the needed parameters to the more complete Connect() method overload.

1
2
3
4
5
6
7
8
byte code = client.Connect(Guid.NewGuid().ToString(), null, null,
false, // will retain flag
MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, // will QoS
true, // will flag
"/will_topic", // will topic
"will_message", // will message
true,
60);

Connect with Username / Password

The authentication feature using username and password is enabled by specifying these parameters in the Connect() method.

byte code = client.Connect(Guid.NewGuid().ToString(), "username", "password");

Publish

As you know, the MQTT protocol supports the publish/subscribe pattern so the main operation you can do with a client for sending messages to other clients is the publish action. The MqttClient class provides the Publish() method to publish a message (with related body) to a specific topic with a defined QoS level. Before you call the above method, you can register an event handler for the MqttMsgPublished event provided by the MqttClient instance to know when the message was (or wasn’t) published to the broker.

1
2
3
4
5
6
client.MqttMsgPublished += client_MqttMsgPublished;

ushort msgId = client.Publish("/my_topic", // topic
                              Encoding.UTF8.GetBytes("MyMessageBody"), // message body
                              MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, // QoS level
                              false); // retained

As you can see, you can specify the destination topic, the message body (as an array of bytes), the QoS level for publishing to the broker and the retain flag. This call returns immediately the id assigned to the message that will be sent shortly after. The library works in an asynchronous way with an internal queue and an internal thread for publishing messages.

1
2
3
4
void client_MqttMsgPublished(object sender, MqttMsgPublishedEventArgs e)
{
     Debug.WriteLine("MessageId = " + e.MessageId + " Published = " + e.IsPublished);
}

The event related to the publish method is raised when the message is published to the broker or when an error is detected. An error means that the client made more attempts to send the message but it couldn’t reach the broker (of course this is true only for QoS level 1 and 2 where an acknowledge sequence from broker is expected). You can check if the message was published or not, using the IsPublished property of the received event args (you receive the MessageId too).

Publish a retained Message

You can publish a retained message simply by setting to true the retain flag parameter in the above Publish() method.

1
2
3
4
ushort msgId = client.Publish("/my_topic", // topic
                              Encoding.UTF8.GetBytes("MyMessageBody"), // message body
                              MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, // QoS level
                              true); // retained

Subscribe

In order to receive messages published on one or more topics from other clients, you need to use Subscribe( ).

1
2
3
ushort msgId = client.Subscribe(new string[] { "/topic_1", "/topic_2" },
     new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE,            
                  MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });

It receives two arrays as input parameters : the former is the list of topics you want to subscribe and the latter is the related list of QoS levels (one for each topic). As for publishing, the MqttClient class provides the MqttMsgSubscribed event that is raised when the client is correctly subscribed to the topic (receiving acknowledge from broker).

1
2
3
4
void client_MqttMsgSubscribed(object sender, MqttMsgSubscribedEventArgs e)
{
     Debug.WriteLine("Subscribed for id = " + e.MessageId);
}

Also in this case, the Subscribe() method returns the id of the subscribe message sent to the broker. You can use it to correlate the information you’ll receive in the event args of the above subscribed event.

After subscribing to a topic, you start to receive messages published on this topic. To be notified about received messages, there is the MqttMsgPublishReceived event you can register to.

1
client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;

The related event args provides you all information about the message received like topic, QoS level, message body (as array of bytes) and the retain flag.

1
2
3
4
void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
     Debug.WriteLine("Received = " + Encoding.UTF8.GetString(e.Message) + " on topic " + e.Topic);
}

Unsubscribe

Unsubscribing from specific topics is very simple using the Unsubscribe() method provided by the MqttClient class.

1
2
3
client.MqttMsgUnsubscribed += client_MqttMsgUnsubscribed;

ushort msgId = client.Unsubscribe(new string[] { "/topic_1", "/topic_2" });

You have to provide the list of topics you want to unsubscribe from. As for the publishing, the MqttClient class provides the MqttMsgUnsubscribed event that is raised when the client receives the confirmation from the broker that the unsubscribe request was successful. As for subscribing, in this case you can use the message id, returned by Unsubscribe() method, for correlating the information received in the event args.

1
2
3
4
void client_MqttMsgUnsubscribed(object sender, MqttMsgUnsubscribedEventArgs e)
{
     Debug.WriteLine("Unsubscribed for id = " + e.MessageId);
}

Disconnect

The disconnection from the broker is possible using the Disconnect() method that is synchronous and returns when all internal threads ends gracefully.

client.Disconnect();

A client can disconnect gracefully using the above method but the connection could be lost due to network problems or closed broker. In this case, you can register to the ConnectionClosed event.

client.ConnectionClosed += client_ConnectionClosed;

Using TLS / SSL

M2Mqtt supports secure connection to an MQTT broker using the SSL/TLS protocol and X509 certificates. First of all you need to get the CA certificate used to sign the broker certificate you’ll connect to. For more information about certificate creation you can read the following article on my Embedded101 community blog (there is an example using OpenSSL). After that, you need to provide the certificate as resource inside your .Net project using a resources file (Resources.resx) that exposes the certificate itself as a byte stream.

1
2
3
4
MqttClient client = new MqttClient("broker.hivemq.com",
                        MqttSettings.MQTT_BROKER_DEFAULT_SSL_PORT,
                        true,
                        new X509Certificate(Resources.m2mqtt_ca));

As you can see, one of the overloads of the MqttClient class constructor has an instance of X509Certificate class as input parameter that we can use to provide our CA certificate from resources file.

To have a more fine grained control on certificate validation you can provide another parameter as RemoteCertificateValidationCallback. This is a callback routine that the .Net runtime calls for you when it needs to validate a server certificate.

1
2
3
4
bool client_RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
     // logic for validation here
}

The above callback provides you all information and data you need to validate the server certificate based on your client application policy.

Author Information

About Paolo Patierno

Senior Software Engineer and Microsoft MVP for Windows Embedded / Internet of Things who has been working on Microsoft technologies since 2006 with all .Net Frameworks (Micro, Compact and Desktop); he has been developing on embedded and mobile systems (based on Windows CE, WindowsPhone/Android and RTOS) since 2010, using C/C++, C# and Java. Focused on IoT and M2M communication. Member of DotNetCampania, TinyCLR.it and Embedded101 communities. Technical writer and owner of some open source projects on CodePlex and GitHub

Website

Contact

<  MQTT Client Library Encyclopedia - MQTT-Client-Framework   |   MQTT Client Library Encyclopedia - Paho Embedded   >