Configurando Arduino y MQTT

Ricardo Vega / 20 octubre 2016
⏰ 7 minutos
POST actualizado con las correcciones de Chano. Muchas gracias :)
La semana pasada te explicaba cómo unir MQTT y Arduino era una opción muy prometedora en tu entorno del Internet de las Cosas. Si no has tenido tiempo de leer el post, te recomiendo que lo hagas ahora mismo ya que hoy nos basaremos en las reflexiones que hicimos anteriormente para centrarnos hoy únicamente en la construcción en sí.
Como ya hablamos, necesitaremos tener configurado un broker, que en mi caso será Mosquitto.
Lo arrancamos y lo dejamos iniciado introduciendo en una consola:
mosquitto -c /usr/local/etc/mosquitto/mosquitto.conf
Vamos a trabajar con un topic
que nombraremos como 'test'. Como recordarás, no
necesitábamos explícitamente definir el topic sino que se creaba
automáticamente en cuanto había un publicador o subscriptor usándolo.
En nuestro caso, vamos a poner un escuchador. Activamos un cliente subscrito al topic 'test' introduciendo en otra consola lo siguiente:
mosquitto_sub -t "test/#" -v
En otra consola, probamos que está funcionando correctamente escribiendo:
mosquitto_pub -t "test" -m "Hello World"
Si todo está correctamente configurado, en la consola en la que abrimos el escuchado veremos que "escucha" el "Hello World".
MQTT y Arduino
Ahora que lo tenemos todo listo, veamos la parte de Arduino que es lo que realmente nos interesa.
Como habrás imaginado, para conseguir una comunicación MQTT, emplearemos una librería. Existen muchas disponibles gracias a la gran (tanto en tamaño como en calidad) comunidad que existe alrededor de Arduino.
Concretamente, nosotros emplearemos una de las más conocidas y es que, tras probar varias alternativas, creo que es la más estable y flexible, lo que facilita su uso tanto hoy como en futuros proyectos que queramos realizar donde intervengan Arduino y MQTT.
Dicha librería es Arduino Client for MQTT y nos provee de un
sencillo cliente que nos permite tanto subscribirnos como publicar contenido
usando MQTT. Internamente, usa la API de Arduino Ethernet Client
lo que lo
hace compatible con un gran número de 'shields' y placas como:
- Arduino Ethernet
- Arduino YUN
- Arduino WiFi Shield
- Intel Galileo/Edison
- ESP8266
Inicialmente, debemos instalar dichar librería para lo cual clonaremos en nuestra carpeta de librerías de Arduino la última versión disponible en el repositorio oficial del proyecto mediante el siguiente comando:
git clone https://github.com/knolleary/pubsubclient.git
Nosotros hoy vamos a emplear un Arduino UNO junto con un Arduino Ethernet y un sensor DHT22. La configuración, semejante a la ya explicada en este post, tiene un cableado muy sencillo que puedes ver en la siguiente imagen:
La Shield Ethernet irá montado encima y la conectaremos a nuestro router a través de un cable de red.
A nivel de código, emplearemos el siguiente:
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT11
// Direccion MAC
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// IP del servidor
IPAddress mqtt_server(192, 168, 1, 38);
// Topic con el que trabajamos
const char* topicName = "test";
DHT dht(DHTPIN, DHTTYPE);
EthernetClient ethClient;
PubSubClient client(ethClient);
void setup()
{
Serial.begin(9600);
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
}
client.setServer(mqtt_server, 1883);
dht.begin();
}
void loop()
{
if (!client.connected()) {
Serial.print("Connecting ...\n");
client.connect("Arduino Client");
}
else {
// Envio
float temp = dht.readTemperature();
char buffer[10];
dtostrf(temp,0, 0, buffer);
client.publish(topicName, buffer);
}
// Tiempo entre envios (en ms)
delay(5000);
}
Con toda la parte hardware montada y con este trozo de código metido en nuestro Arduino, podemos alimentarlo y veremos como, cada cinco segundos, en la terminal que habíamos abierto y que estaba subscrita al topic 'test' irán apareciendo la medición de temperatura que realiza nuestro sensor cada cinco segundos.
Ahora, podemos probar la comunicación opuesta, es decir, recibir mensajes en nuestro Arduino a través de MQTT. En esta ocasión, no necesitamos nada más que el Arduino UNO y la placa Ethernet.
El código en esta ocasión será:
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
// Direccion MAC
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// IP del servidor
IPAddress mqtt_server(192, 168, 1, 38);
// Topic con el que trabajamos
const char* topicName = "test";
EthernetClient ethClient;
PubSubClient client(ethClient);
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
int i=0;
for (i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
void setup()
{
Serial.begin(9600);
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
}
client.setServer(mqtt_server, 1883);
client.setCallback(callback)
}
void loop()
{
if (!client.connected()) {
Serial.print("Connecting ...");
if (client.connect("rece_arduino")) {
Serial.println("connected");
client.subscribe(topicName);
} else {
delay(5000);
}
}
// Cliente a la escucha
client.loop();
}
Si tienes dos Arduinos, podrás probar ambos a la vez pero recuerda que deberás modificar algunos datos que deben ser únicos en la red como la dirección MAC o la IP (la del server lógicamente se mantiene).
De cualquier modo, vamos a hacer la prueba suponiendo que sólo tuviéramos un Arduino. Para ello, conectamos nuestro Arduino UNO con el código segundo subido y la placa Ethernet y los dejamos conectados por USB al ordenador.
Abrimos el monitor serie del IDE de Arduino y comprobamos que recibimos el mensaje "Connected". Ahora vamos a una consola del sistema y en ella ejecutamos de nuevo:
mosquitto_pub -t "test" -m "Hello World"
Veremos como en nuestro monitor serie aparece el mensaje "Hello World" que acabamos de mandar.
Esta información, en vez de "imprimirla" a través del puerto serie, podría servirnos dentro de la lógica de nuestra aplicación pero ya habrás advertido como, aunque el envío es muy sencillo, la recepción, al ser byte a byte, es algo más compleja requiriendo un tratamiento algo mayor.
De cualquier modo, no es nada excesivamente complicado y podríamos tener el valor recibido en una variable con una función tan sencilla como:
String data;
void callback(char* topic, byte* payload, unsigned int length) {
char dataArray[length];
for (int i=0;i<length;i++) {
dataArray[i] = (char)payload[i];
}
data = str(dataArray)
}
En la variable data tendriamos en formato String el contenido recibido.
Conclusiones
Esta entrada completa la de la semana pasada y demuestra cómo todas las ventajas que veíamos al uso de MQTT como protocolo de comunicación con Arduino y nuestro sistema no implican una elevada complicación.
Prácticamente la totalidad de los proyectos que realices podrán reutilizar gran parte del código y los conocimientos que hemos aprendido a lo largo de esta entrada.
Además, la posibilidad de usar esta librería con otras placas (como ESP8266) nos permite una gran flexibilidad a la hora de construir nuestro proyecto.
Aplicando estos sencillos pasos / configuraciones, somos capaces de conectar el nivel más bajo de la pirámide del Internet de las Cosas (la sensorización) con las capas intermedias que se encargan de procesar y consumir dicha información, tanto de forma discrecional como empleando técnicas más complejas de análisis de datos.
Todo ello, sin comprometer la estabilidad y escalabilidad del sistema global, pudiendo añadir tantos sensores como necesitemos de una forma sencilla y sin preocuparnos de configuraciones extra.
A partir de este momento, deberías empezar a ser capaz de construir soluciones de mayor complejidad en el "mundillo" del Internet de las Cosas. Estoy impaciente por conocerlas :)
La próxima semana completaremos un poco más estas dos entradas, hablando de cómo podemos securizar un broker MQTT como Mosquitto para añadir una capa de complejidad extra a nuestras soluciones.
Esta entrada ha tenido "chicha" suficiente como para que estés un buen rato "cacharreando". Espero que de ahí salgan nuevas e interesantes ideas.
¿Tienes alguna duda? ¿Qué te ha parecido esta entrada? No dudes en ponerte en contactato conmigo a través de los comentarios o las redes sociales.
Si aún no me sigues en Twitter, te recomiendo que, si te gusta mi contenido, lo hagas ya que estoy preparando alguna sorpresa a través de ese canal ;). Además es una buena forma de comunicarte conmigo y suelo publicar distintas noticias que considero relevantes del mundo del Internet de las Cosas.
Sígueme en @ricveal
¡Nos vemos la próxima semana con más contenido!
Subscríbete a mi newsletter
Actualmente estoy llevando a cabo algunos cambios en mi Newsletter y no es posible apuntarse 😞