Introducción a MQTT con Node-RED, Raspberry Pi y Arduino

Autor: Oscar Gonzalez

Introducción a MQTT con Node-RED, Raspberry Pi y Arduino

Tiempo de lectura: 21 minutos

En ésta guía aprenderás cómo instalar Node-RED en Raspberry Pi para automatizar procesos IoT con MQTT y Arduino ESP8266/ESP32

Introducción a MQTT con Node-RED, Raspberry Pi y Arduino

  • 0

0 Principiante

Ejemplo MQTT con Arduino

Para probar todo el sistema MQTT con Node-Red vamos a montar un dispositivo físico que pueda interactuar con el servidor en ambas direcciones: Enviar y recibir datos por MQTT

Eso quiere decir que nuestro dispositivo será a la vez un suscriptor y un publisher. Para eso usaremos una placa ESP32 con un LED y un pulsador. Para completar el sistema debemos realizar los siguientes pasos:

  1. Crear un dispositivo físico IoT
  2. Conectar a la red Wifi
  3. Suscribirse a un topic
  4. Publicar en el topic al detectar el pulsador

Ten en cuenta por supuesto que aunque utilicemos un dispositivo físico, MQTT no se limita a eso, ya que puedes utilizarlo para comunicar diversos servicios "no físicos" como software, servicios online etc. La magia ocurre cuando conectas un dispositivo físico con un software y viceversa, ¡es realmente muy poderoso!

MQTT con Arduino, ESP8266 y ESP32

Éste es un ejemplo extremadamente sencillo y usaremos un Arduino MKR 1000 que ya tiene incorporado un módulo Wifi. Por supuesto, no tienes por qué utilizar ésta placa en concreto, puedes utilizar cualquier otra, básicamente cualquier placa que sea programable con Arduino y tenga conectividad Wifi o Ethernet (sí, todavía existen los cables de red! ;D)

Te dejo aquí algunas alternativas que puedes utilizar:

Arduino MKR1000 WIFI

Arduino MKR1000 WIFI

Placa original Arduino MKR1000 Wifi con procesador ARM SAMD21, Wifi y encriptación por hardware.

Éste producto no está disponible para comprar

Ver ficha


NodeMCU V3 Wifi - ESP8266, CH340

NodeMCU V3 Wifi - ESP8266, CH340

Placa NodeMCU Wifi para desarrollo IoT basada en ESP8266 / CH340G

3,95€

Comprar


Adafruit Feather HUZZAH ESP8266 WiFi

Adafruit Feather HUZZAH ESP8266 WiFi

Adafruit Feather HUZZAH Wifi con ESP8266 y cargador de baterías LiPo integrado

17,90€

Comprar


Sparkfun ESP8266 Thing - Dev

Sparkfun ESP8266 Thing - Dev

Placa de desarrollo para ESP8266 con versor USB FTDI integrado

Éste producto no está disponible para comprar

Ver ficha


Wemos ESP8266 OLED

Wemos ESP8266 OLED

Combina un módulo Wifi ESP8266 con una pantalla OLED monocromo compartible con Arduino

7,90€

Comprar


Wemos D1 Mini ESP8266 Wifi

Wemos D1 Mini ESP8266 Wifi

Placa con ESP8266 Wifi (ESP-12E) muy pequeña compartible con Arduino con conector USB y pines de expansión ideal para proyectos IoT

4,10€

Comprar


Todas éstas placas utilizan el ESP8266. Puedes utilizar también placas basadas en ESP32, pero no todas las librerías MQTT son compatibles, por lo tanto si utilizas una placa ESP32, debes revisar que la librería que utilices sea compatible.

Instalación de librería MQTT

Para poder comunicarse con el servidor MQTT, usaremos la librería oficial ArduinoMQTTClient que puedes encontrar en Github o directamente desde el gestor de librerías de Arduino.

Lectura recomendada

Si no tienes cómo claro se hace, puedes repasar éste tutorial de instalación de librerías Arduino

Existen por supuesto otras librerías como la MQTTClient de Adafruit o PubSub y cada una tiene sus funcionalidades, pero en su esencia son todas lo mismo, así que elige la que prefieras.

Código de ejemplo

El código se basa en el ejemplo mismo de la librería y se entiende por si solo. Más abajo desglosaremos las partes más importantes que debes modificar para hacerlo funcionar. El código se suscribe a un topic y publica un mensaje cada segundo (y sin usar delay!). Ésta parte envía datos hacia el Broker.

Ahora haremos que también reciba datos del Broker, conectando un diodo LED. Es un ejemplo muy sencillo, pero de ésta manera podremos encender el LED desde Node-Red y tendremos el bucle de envio/recepción completo.

/*
  ArduinoMqttClient - WiFi Simple Sender

  This example connects to a MQTT broker and publishes a message to
  a topic once a second.

  The circuit:
  - Arduino MKR 1000, MKR 1010 or Uno WiFi Rev.2 board

  This example code is in the public domain.
*/

#include <ArduinoMqttClient.h>
#if defined(ARDUINO_SAMD_MKRWIFI1010) || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_AVR_UNO_WIFI_REV2)
  #include <WiFiNINA.h>
#elif defined(ARDUINO_SAMD_MKR1000)
  #include <WiFi101.h>
#elif defined(ARDUINO_ESP8266_ESP12)
  #include <ESP8266WiFi.h>
#endif

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

// To connect with SSL/TLS:
// 1) Change WiFiClient to WiFiSSLClient.
// 2) Change port value from 1883 to 8883.
// 3) Change broker value to a server with a known SSL/TLS root certificate 
//    flashed in the WiFi module.

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

const char broker[] = "192.168.1.50";
int        port     = 1883;
const char topic[]  = "prueba/mqtt";

const long interval = 1000;
unsigned long previousMillis = 0;

int count = 0;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // attempt to connect to Wifi network:
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }

  Serial.println("You're connected to the network");
  Serial.println();

  // You can provide a unique client ID, if not set the library uses Arduino-millis()
  // Each client must have a unique client ID
  // mqttClient.setId("clientId");

  // You can provide a username and password for authentication
  // mqttClient.setUsernamePassword("username", "password");

  Serial.print("Attempting to connect to the MQTT broker: ");
  Serial.println(broker);

  if (!mqttClient.connect(broker, port)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());

    while (1);
  }

  Serial.println("You're connected to the MQTT broker!");
  Serial.println();
}

void loop() {
  // call poll() regularly to allow the library to send MQTT keep alives which
  // avoids being disconnected by the broker
  mqttClient.poll();

  // avoid having delays in loop, we'll use the strategy from BlinkWithoutDelay
  // see: File -> Examples -> 02.Digital -> BlinkWithoutDelay for more info
  unsigned long currentMillis = millis();
  
  if (currentMillis - previousMillis >= interval) {
    // save the last time a message was sent
    previousMillis = currentMillis;

    Serial.print("Sending message to topic: ");
    Serial.println(topic);
    Serial.print("hello ");
    Serial.println(count);

    // send message, the Print interface can be used to set the message contents
    mqttClient.beginMessage(topic);
    mqttClient.print("hello ");
    mqttClient.print(count);
    mqttClient.endMessage();

    Serial.println();

    count  ;
  }
}

Veamos las partes más importantes a tener en cuenta. Lo primero por supuesto, debemos tener la placa conectada a nuestra red Wifi. Paro, tocaremos estas líneas con nuestra configuración. 

También puedes utilizar el fichero arduino_secrets.h con lo mismo o directamente reemplazar los valores:

char ssid[] = SECRET_SSID;        // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

Luego necesitamos indicar dónde está nuestro servidor MQTT (Broker), el puerto de conexión por si no utilizar el que viene por defecto y el Topic a donde queremos publicar los mensajes. 

En servidor debes indicar la dirección IP de tu Raspberry Pi. No copies y pegues ya que tu configuración será diferente a la mostrada en éste ejemplo. Aunque a éstas alturas del tutorial ya deberías saber la IP de tu Raspberry Pi, ante la duda puedes consultarlo desde la consola con el comando ipconfig. El puerto será el 1883 en este caso y para el topic usaremos "prueba/mqtt".

const char broker[] = "192.168.1.50";
int        port     = 1883;
const char topic[]  = "prueba/mqtt";

Con esto podremos cargar el programa en la placa y tener todo listo para publicar mensajes. Ahora nos falta preparar el Node-Red para que reciba y muestre esos mensajes.

Crear un flow MQTT en Node-Red

El flow es la parte lógica de Node-Red y que va a manejar los mensajes MQTT. El este caso será muy simple, pero aquí puedes hacer que tu proyecto reacciones a sensores, active cosas, guardar datos o cualquier otra cosa que quieras hacer con el sistema.

Un ejemplo clásico sería tener un dispositivo wifi, un ESP8266 por ejemplo, que tenga un sensor de temperatura y notifique por MQTT al Broker la temperatura. Luego con otra placa igual que tenga un relé, podríamos construir un flow en Node-Red para que una vez llegado a una temperatura fijada, que se active el relé. Esto podría encender el aire acondicionado cuando hace mucho calor por ejemplo. De ésta forma tenemos un sistema inteligente que reacciona a eventos.

Para crear el flow, usaremos bloques visuales, en este caso solo 2: mqtt-in y mqtt-out. En medio de todo esto podremos complicarnos todo lo que nos dé la gana, pero eso ya lo dejo a tu gusto para que investigues todas las posibilidades del sistema.

Configurar el Broker Mosquitto en Node-Red

Antes de poder utilizar los bloques MQTT, es necesario configurar Node-Red para que sepa dónde está el servidor, en este caso Mosquitto. Para eso, haremos doble click sobre uno de los bloques mqtt y veremos su configuración (por ahora vacía). Pulsaremos sobre el icono de editar.

Una vez hecho, podremos añadir la configuración de nuestro servidor MQTT Mosquitto. Recuerda que ésto solo hay que hacerlo una vez, ya que luego ya podremos utilizando en Node-Red.

En nuestro caso y como el servidor Mosquitto está en el mismo sitio que Node-Red, pondremos "localhost" como "Server" y el resto todo por defecto. También es interesante ponerte un nombre al bloque, sobre todo si vamos a utilizar varios servidores, pero eso no es habitual.

Ahora volvamos a nuestro bloque MQTT-IN. Solo debemos indicarle cómo debe funcionar y sobre todo a qué topic debe suscribirse. En éste caso es "prueba/mqtt"

El servidor Mosquitto que hemos configurado previamente se selecciona arriba. La acción predeterminada es que se suscriba a un solo topic, pero podríamos eventualmente escucharlo todo.

El indicador QOS (calidad de servicio) indica la consistencia con la que los mensajes de este tema se tienen que entregar a los clientes y solo tiene tres valores posibles:

  • 0: No confiable, el mensaje se entrega como mucho una vez, si el cliente no está disponible en ese momento se perderá el mensaje.
  • 1: el mensaje se debería entregar al menos una vez.
  • 2: el mensaje se debería entregar exactamente una vez.

Finalmente pondremos un nombre al bloque y tendremos el sistema funcionando, quedando algo tal que así:

Fíjate que una vez hechos todos los pasos anteriores, los bloques aparecerán con un solo circulo azul sin el triangulo rojo, indicando que están correctamente conectados al servidor MQTT Mosquitto.

Cómo importar un flow en Node-Red

Importar Flow en Node-Red

Importar Flow en Node-Red

Lo más recomendable es crear los bloques tu mismo a mano, pero si quieres simplemente ver qué hace, node-red tiene una opción para importar y exportar flow. Lo puedes hacer desde el menú "Import" y en la ventana, pegar el siguiente código:

[{"id":"f6f2187d.f17ca8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"97540079028cd0d4","type":"mqtt in","z":"f6f2187d.f17ca8","name":"","topic":"prueba/mqtt","qos":"2","datatype":"auto","broker":"917717f3ee821134","nl":false,"rap":true,"rh":0,"inputs":0,"x":310,"y":180,"wires":[["d6e260943bc82140"]]},{"id":"90c1e1cf60a4e9a4","type":"mqtt out","z":"f6f2187d.f17ca8","name":"","topic":"","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"917717f3ee821134","x":530,"y":260,"wires":[]},{"id":"d6e260943bc82140","type":"debug","z":"f6f2187d.f17ca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":510,"y":180,"wires":[]},{"id":"7e1c9e828dc21aed","type":"inject","z":"f6f2187d.f17ca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":300,"y":260,"wires":[["90c1e1cf60a4e9a4"]]},{"id":"917717f3ee821134","type":"mqtt-broker","name":"mi_mosquitto_server","broker":"localhost","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]

Conclusiones

Espero que ésta guía te haya servidor para aprender un poco más sobre MQTT y Node-Red con Arduino y que te ayude a crear proyectos mucho más ambiciosos. Si practicas un poco y eliges las placas correctas, puedes automatizar muchas cosas de una forma muy sencilla.

Algunas ideas de proyectos con Node-Red y MQTT

Este es un sistema muy potente y puedes incluso llegar a tener un automatización muy compleja dependiendo de tus requisitos. Lo mejor es ir haciendo proyectos pequeños e ir aprendiendo cada vez más cosas. 

Te dejo aquí abajo solo una pocas ideas de muchas cosas que puedes automatiar con Node-Red:

  • Encendido automático de luces cuando entras en una habitación
  • Notificaciones por email, Telegram etc cuando ocurre algo
  • Automatizar el clima de acuarios y terrarios

El límite siempre será tu imaginación!