mqtt-protocolo-iot-nanoframework

MQTT in nanoFramework: Publish and Subscribe

  • 5 min

MQTT is a lightweight messaging protocol based on publish and subscribe topics.

So far we’ve used HTTP. It’s a great protocol, but it has a problem: it’s “heavy” and works on demand. Imagine you want to turn on a light in your home from your phone. If you use HTTP, your microcontroller would have to ask the server every second: “Any orders? Any orders? Any orders?”. This is inefficient and drains the battery.

The MQTT protocol (Message Queuing Telemetry Transport) changes the rules of the game. It is a lightweight protocol, designed for unstable networks and based on the Publish / Subscribe model.

In this post, we will learn how to use the nanoFramework.M2Mqtt library to connect our device to a Broker, send data, and receive instant commands.

For this tutorial, you need to install the NuGet package: nanoFramework.M2Mqtt

Publish and Subscribe Architecture

In MQTT we have three actors:

  1. The Broker: This is the “postman” or central server (e.g., Mosquitto, HiveMQ, Azure). Its only job is to receive messages and distribute them.
  2. The Publisher: Who sends data (e.g., Your ESP32 sends temperature).
  3. The Subscriber: Who wants to receive that data (e.g., Your phone or a database).

The powerful idea is that the Publisher and Subscriber do not know each other. They only know the Broker and the Topic (the “subject” of the message).

Configure the MQTT Client

We will connect our ESP32 to a free public Broker for testing, such as broker.hivemq.com or test.mosquitto.org.

Public brokers are for one-off tests. Use a topic that is hard to collide and do not publish credentials or private data, because other clients can subscribe to it.

using System;
using System.Text;
using System.Threading;
using System.Diagnostics;
using uPLibrary.Networking.M2Mqtt;       // <--- Library namespace
using uPLibrary.Networking.M2Mqtt.Messages;

public static void StartMQTT()
{
    // 1. Define the Broker (IP or Domain)
    string brokerHost = "broker.hivemq.com";
    
    // 2. Create the client
    MqttClient client = new MqttClient(brokerHost);

    // 3. Generate a unique ID (if two clients have the same ID, the broker kicks out the first)
    string clientId = Guid.NewGuid().ToString();

    // 4. Connect
    Debug.WriteLine("Connecting to Broker...");
    
    // Connect returns an error code (0 = success)
    byte code = client.Connect(clientId);

    if (code == MqttMsgConnack.CONN_ACCEPTED)
    {
        Debug.WriteLine("Connected to MQTT!");
    }
    else
    {
        Debug.WriteLine($"Connection error: {code}");
    }
}
Copied!

Publish Data

We are a temperature sensor. We want to tell the world it’s 25 degrees. Simply choose a topic and send the bytes.

string topic = "luisllamas/course/temperature";
string message = "{ \"value\": 25.5 }"; // Better if you use serialized JSON

// Convert string to bytes
byte[] buffer = Encoding.UTF8.GetBytes(message);

// Publish
// QoS Level 1, Retain = false
client.Publish(topic, buffer, MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false);

Debug.WriteLine($"Message sent to {topic}");
Copied!

If you use a program like MQTT Explorer on your PC and subscribe to that topic, you’ll see the message appear instantly!

Subscribe to Receive Commands

Now we want to control an LED. The device must “listen” to the topic luisllamas/course/led.

This works via Events.

  1. We subscribe to the topic.
  2. We define which function runs when a message arrives.
// ... (After connecting)

// 1. Assign the event handler
client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;

// 2. Subscribe to the topic
// We can subscribe to several at once. Here just one with QoS 1.
client.Subscribe(
    new string[] { "luisllamas/course/led" }, 
    new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE }
);

Debug.WriteLine("Listening for commands...");
Copied!

The Event Handler

Here we process the incoming message. This is a library callback, so it’s good practice to finish quickly and delegate long tasks to another thread.

private static void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
    // 1. Convert the received bytes to text
    string message = new string(Encoding.UTF8.GetChars(e.Message));
    string topic = e.Topic;

    Debug.WriteLine($"Message received on [{topic}]: {message}");

    // 2. Act according to the message
    if (message == "ON")
    {
        // Turn on LED (using GpioController)
        Debug.WriteLine("--> TURNING LED ON");
    }
    else if (message == "OFF")
    {
        // Turn off LED
        Debug.WriteLine("--> TURNING LED OFF");
    }
}
Copied!

Maintaining the Connection

Unlike HTTP, MQTT keeps a TCP connection open permanently. The client sends “heartbeats” (pings) to the broker periodically to say “I’m still alive”.

The nanoFramework.M2Mqtt library handles this automatically in the background. However, if Wi-Fi goes down, the MQTT connection will break.

It is your responsibility to:

  1. Detect disconnection (client.ConnectionClosed).
  2. Attempt to reconnect (wait some time and call Connect again).
client.ConnectionClosed += (sender, e) =>
{
    Debug.WriteLine("Connection lost");
    // Signal a supervisor thread to retry with wait and backoff.
};
Copied!

Choosing a Broker

For learning, public brokers (HiveMQ, Eclipse) are fine. But never use them for serious things, since anyone can read your messages if they guess the topic.

For real projects, you have two options:

  1. Local (Private): Install Mosquitto on a Raspberry Pi or in a Docker on your server. You have full control and minimal latency.
  2. Cloud (Scalable): Use services like HiveMQ Cloud, AWS IoT, or Azure IoT Hub.