MQTT es un protocolo de mensajería ligero basado en publicar y suscribirse a temas.
Hasta ahora hemos usado HTTP. Es un protocolo genial, pero tiene un problema: es “pesado” y funciona bajo demanda. Imagina que quieres encender una luz en tu casa desde el móvil. Si usas HTTP, tu microcontrolador tendría que estar preguntando al servidor cada segundo: “¿Hay órdenes? ¿Hay órdenes? ¿Hay órdenes?”. Esto es ineficiente y gasta batería.
El protocolo MQTT (Message Queuing Telemetry Transport) cambia las reglas del juego. Es un protocolo ligero, diseñado para redes inestables y basado en el modelo Publicar / Suscribir.
En esta entrada aprenderemos a usar la librería nanoFramework.M2Mqtt para conectar nuestro dispositivo a un Broker, enviar datos y recibir órdenes instantáneas.
Para este tutorial necesitas instalar el paquete NuGet: nanoFramework.M2Mqtt
Arquitectura de publicación y suscripción
En MQTT tenemos tres actores:
- El Broker: Es el “cartero” o servidor central (Ej. Mosquitto, HiveMQ, Azure). Su único trabajo es recibir mensajes y repartirlos.
- El Publicador: Quien envía un dato (Ej. Tu ESP32 envía temperatura).
- El Suscriptor: Quien quiere recibir ese dato (Ej. Tu móvil o una base de datos).
La idea potente es que el Publicador y el Suscriptor no se conocen entre sí. Solo conocen al Broker y al Tópico (el “asunto” del mensaje).
Configurar el cliente MQTT
Vamos a conectar nuestro ESP32 a un Broker público gratuito para probar, como broker.hivemq.com o test.mosquitto.org.
Los brokers públicos sirven para pruebas puntuales. Usa un topic difícil de colisionar y no publiques credenciales ni datos privados, porque otros clientes pueden suscribirse a él.
using System;
using System.Text;
using System.Threading;
using System.Diagnostics;
using uPLibrary.Networking.M2Mqtt; // <--- Namespace de la librería
using uPLibrary.Networking.M2Mqtt.Messages;
public static void IniciarMQTT()
{
// 1. Definir el Broker (IP o Dominio)
string brokerHost = "broker.hivemq.com";
// 2. Crear el cliente
MqttClient client = new MqttClient(brokerHost);
// 3. Generar un ID único (si dos clientes tienen el mismo ID, el broker expulsa al primero)
string clientId = Guid.NewGuid().ToString();
// 4. Conectar
Debug.WriteLine("Conectando al Broker...");
// Connect devuelve un código de error (0 = éxito)
byte codigo = client.Connect(clientId);
if (codigo == MqttMsgConnack.CONN_ACCEPTED)
{
Debug.WriteLine("¡Conectado a MQTT!");
}
else
{
Debug.WriteLine($"Error de conexión: {codigo}");
}
}Publicar datos
Somos un sensor de temperatura. Queremos decirle al mundo que hace 25 grados. Simplemente elegimos un tópico y enviamos los bytes.
string tema = "luisllamas/curso/temperatura";
string mensaje = "{ \"valor\": 25.5 }"; // Mejor si usas JSON serializado
// Convertir string a bytes
byte[] buffer = Encoding.UTF8.GetBytes(mensaje);
// Publicar
// QoS Level 1, Retain = false
client.Publish(tema, buffer, MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, false);
Debug.WriteLine($"Mensaje enviado a {tema}");Si usas un programa como MQTT Explorer en tu PC y te suscribes a ese tema, ¡verás aparecer el mensaje instantáneamente!
Suscribirse para recibir órdenes
Ahora queremos controlar un LED. El dispositivo debe “escuchar” el tópico luisllamas/curso/led.
Esto funciona mediante Eventos.
- Nos suscribimos al tema.
- Definimos qué función se ejecuta cuando llega un mensaje.
// ... (Después de conectar)
// 1. Asignar el manejador de eventos
client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
// 2. Suscribirse al tema
// Podemos suscribirnos a varios a la vez. Aquí solo a uno con QoS 1.
client.Subscribe(
new string[] { "luisllamas/curso/led" },
new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE }
);
Debug.WriteLine("Escuchando órdenes...");El manejador del evento
Aquí procesamos el mensaje entrante. Se trata de un callback de la librería, así que conviene que termine rápido y delegue las tareas largas a otro hilo.
private static void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
// 1. Convertir los bytes recibidos a texto
string mensaje = new string(Encoding.UTF8.GetChars(e.Message));
string tema = e.Topic;
Debug.WriteLine($"Mensaje recibido en [{tema}]: {mensaje}");
// 2. Actuar según el mensaje
if (mensaje == "ON")
{
// Encender LED (usando GpioController)
Debug.WriteLine("--> ENCENDIENDO LED");
}
else if (mensaje == "OFF")
{
// Apagar LED
Debug.WriteLine("--> APAGANDO LED");
}
}Mantener la conexión
A diferencia de HTTP, MQTT mantiene una conexión TCP abierta permanentemente. El cliente envía “latidos” (pings) al broker periódicamente para decir “sigo vivo”.
La librería nanoFramework.M2Mqtt gestiona esto automáticamente en segundo plano. Sin embargo, si el Wi-Fi se cae, la conexión MQTT se romperá.
Es tu responsabilidad:
- Detectar la desconexión (
client.ConnectionClosed). - Intentar reconectar (esperar un tiempo y llamar a
Connectde nuevo).
client.ConnectionClosed += (sender, e) =>
{
Debug.WriteLine("Conexión perdida");
// Señalar a un hilo de supervisión para que reintente con espera y backoff.
};Elegir un broker
Para aprender, los brokers públicos (HiveMQ, Eclipse) están bien. Pero nunca los uses para cosas serias, ya que cualquiera puede leer tus mensajes si adivina el tópico.
Para proyectos reales tienes dos opciones:
- Local (Privado): Instalar Mosquitto en una Raspberry Pi o en un Docker en tu servidor. Tienes control total y latencia mínima.
- Cloud (Escalable): Usar servicios como HiveMQ Cloud, AWS IoT o Azure IoT Hub.