Вы находитесь на странице: 1из 202

Índice de contenidos

1 Introducción
1.1 ¿De qué trata este libro?
1.2 Material necesario

2 MQTT
2.1 ¿Qué es MQTT?
2.1.1 ¿Quién creó MQTT?
2.1.2 ¿Es un estándar de comunicaciones?
2.1.3 ¿Es un protocolo seguro?
2.2 Arquitectura MQTT
2.2.1 Arquitectura publicación/suscripción de MQTT
2.2.2 ¿Qué es un topic?
2.2.3 Sintaxis de los topic
2.2.4 Estructura de un mensaje MQTT
2.2.5 ¿Cómo funciona la arquitectura MQTT?
2.2.6 Servicio de Calidad o QoS
2.3 Instalación Mosquitto en Raspberry Pi
2.3.1 Instalación Mosquitto en Raspberry Pi
2.3.2 Instalar cliente MQTT en Raspberry Pi
2.3.3 Ejemplo con Mosquitto MQTT
2.3.3.1 Comando mosquitto_sub
2.3.3.2 Comando mosquitto_pub
2.3.4 Primera prueba con el protocolo MQTT
2.3.5 Configurando una IP fija en Raspberry Pi
2.4 Mensajes con MQTT
2.4.1 Instalando la librería PubSubClient
2.4.2 Enviando un mensaje a través del protocolo MQTT con NodeMCU

3 Node-RED
3.1 Instalando Node-RED en Raspberry Pi
3.1.1 Ejecutando Node-RED
3.1.2 Ejecución automática de Node-RED con Raspbian
3.2 Accediendo al editor
3.2.1 Nodos
3.2.2 Paneles de información
3.2.3 Área de trabajo de flujos (flows)
3.3 Primer flujo de trabajo
3.3.1 Cambiar el payload o la carga útil
3.4 MQTT y Node-Red

1
3.4.1 Instalando nodos en Node-RED
3.4.2 Encendiendo y apagando el LED
3.4.2.1 Nodo de salida MQTT
3.4.2.2 Añadiendo el payload al mensaje
3.5 Panel de control con Node-RED
3.5.1 Configurar el dashboard de Node-RED
3.5.2 Abrir panel dashboard
3.5.3 Crear una pestaña o layout del dashboard
3.5.4 Añadir un grupo a la pestaña
3.5.5 Añadir un widget
3.5.6 Conectando el panel de control con MQTT
3.6 Capturando datos con Node-RED
3.6.1 Nodo de entrada MQTT
3.6.2 Conectando el sensor DHT11
3.6.2.1 Circuito eléctrico
3.6.2.2 Integración con el código de MQTT
3.6.2.2.1 Importar librerías
3.6.2.2.2 Declaración de variables
3.6.2.2.3 Función setup
3.6.2.2.4 Función setup_wifi
3.6.2.2.5 Función callback
3.6.2.2.6 Función loop
3.6.2.2.7 Función reconnect
3.6.2.3 Código completo
3.7 Mostrando los datos en la interfaz web
3.7.1 Añadiendo un nodo gauge
3.7.2 Añadiendo un nuevo grupo
3.7.3 Añadiendo un gráfico de histórico
3.7.4 Cambiando el aspecto del panel de control

4 Relé Wifi Sonoff y Node-RED


4.1 Sonoff WiFi Basic
4.1.1 Circuito eléctrico Sonoff
4.1.2 Acceso a los pines
4.1.3 Adaptador TTL USB a Serie
4.1.4 Soldando los pines en el Sonoff
4.1.5 Configuración del IDE de Arduino
4.1.6 Hola mundo con el relé Sonoff
4.1.7 Subiendo el código al ESP8266
4.2 Relé WiFi Sonoff y Node-RED
4.2.1 Programando el relé Sonoff

2
4.2.1.1 Instalando librería WiFiManager
4.2.1.2 Conectando con MQTT
4.2.1.3 Importación de librerías
4.2.1.4 Declaración de variables
4.2.1.5 Función setup
4.2.1.6 Función callback
4.2.1.7 Función loop
4.2.1.8 Función reconnect
4.2.1.9 Función enviarEstadoMQTT
4.2.1.10 Probando el código
4.2.2 Conectando el relé Sonoff a la red eléctrica
4.2.3 Controlando el relé Sonoff con Node-RED

Anexo 1: Importar o exportar nodos


Exportar nodos
Importar nodos

Anexo 2: Configuración de Node-RED

Copyright 2018 Luis del Valle, Programarfacil.com

Publicado por Programarfacil.com

El contenido de este libro, a menos que se indique lo contrario, es Copyright 2018 de Luis del Valle de
Programarfacil.com​. Tiene todos los derechos reservados. Libros como este son posibles gracias al tiempo
invertido por los autores. Si has recibido este libro y no lo has comprado, considera la posibilidad de comprar un
ejemplar para que nuevos libros puedan ser creados.

3
1 Introducción
En el proceso de creación de un dispositivo o servicio del IoT se ven involucrados dos
actores principales. Por un lado el dispositivo que adquiere los datos del entorno físico, por
otro lado el servidor que será encargado de recolectar esos datos.

En la parte donde se adquieren datos, hemos sufrido en los últimos 2 años una gran
revolución con la entrada en escena de microcontroladores como es el ESP8266.

Gracias a su reducido coste y a la integración con la plataforma de Arduino, la tecnologías


del IoT y la automatización del hogar se han puesto al alcance de cualquier persona.

En la parte de sensorización también estamos viendo como cada vez los componentes son
más fiables y económicos.

Ya no hace falta gastarse cientos de euros para automatizar el hogar y tampoco hace falta
estudiar una carrera universitaria para desarrollar este tipo de dispositivos.

En la parte del servidor también estamos asistiendo a una gran revolución por parte de la
gestión de datos. Existen cientos de librerías, frameworks y plataformas que nos permiten
recopilar esos datos y convertirlos en información útil para nosotros.

Una de las herramientas más innovadoras es Node-RED. Un servicio basado en NodeJS


que facilita la tarea de gestionar dispositivos del IoT en nuestra casa o empresa.

Este libro pretende hacer un recorrido de principio a fin, para que tu mismo puedas hacer
tus propios desarrollos y proyectos enfocados a la automatización del hogar y al IoT.

Para conseguir esto vamos a utilizar ESP8266 en la parte de adquisición de datos, MQTT
como protocolo de comunicación y Node-RED con Raspberry Pi en la parte de gestión del
servidor.

4
1.1 ¿De qué trata este libro?
En la primera parte del libro comenzaré hablando del protocolo MQTT donde veremos qué
es y cómo podemos utilizarlo para enviar datos con NodeMCU, la placa de desarrollo
basada en el ESP8266.

Como servidor o broker MQTT utilizaremos una Raspberry Pi por su bajo precio y su bajo
consumo, donde instalaremos Mosquitto.

En la parte de servidor veremos cómo configurar Node-RED con Raspberry Pi. Crearemos
nuestros propios flujos de trabajo y conectaremos con NodeMCU a través del protocolo
MQTT.

En la última parte trabajaremos con el relé Sonoff de Itead especialmente diseñado para la
automatización del hogar.

Este dispositivo tiene incorporado un ESP8266 y comprobarás cómo lo podemos ​hackear


para cargar nuestro propio programa para conectarlo con Node-RED.

Se trata de un libro muy práctico donde encontrarás tutoriales paso a paso para montar todo
el sistema en tu casa o trabajo.

1.2 Material necesario


El material lo iré describiendo a lo largo de los capítulos. Aquí te hago un resumen de lo que
vamos a necesitar por si quieres ir adquiriendo los componentes.

5
Componente Amazon Aliexpress

NodeMCU 7,5€ 6€

Kit Raspberry Pi 57€ 53€

Sensor DHT11 3€ 1,5€

Relé Sonoff 9,5€ 4,5€

Adaptador USB a Serie 3€ 2€

* Los precios pueden haber variado desde la última revisión.


** Si quieres rapidez y garantías compra en Amazon.

6
2 MQTT
Para hablar del protocolo MQTT tenemos que remontarnos en el tiempo por un momento.
Este protocolo permite que las máquinas hablen entre sí es decir, de máquina a máquina o
M2M (del inglés ​Machine To Machine​).

En un extremo tenemos un usuario final, en este caso es un dispositivo capaz de capturar


información a través de sensores. Información como la temperatura, presión, humedad,
niveles o cosas así. Toda esta información se envía a través de las redes de datos.

Durante mucho tiempo, esta arquitectura o disposición nos ha servido. Dispositivos


enviando datos para ser almacenados en servidores. Sin embargo, las cosas o los objetos
cada vez tienen más conectividad.

En general, como sociedad, nos hemos vuelto más conectados. De repente en este
panorama ha surgido una nueva tecnología que se llama Internet de las Cosas o IoT (del
inglés ​Internet of Things​).

Esto ha hecho que la red de dispositivos que ahora pueden comunicarse entre sí, haya
eclosionado. Cada vez existen más cosas u objetos conectados a Internet.

Entonces, lo que ha sucedido es que hay una necesidad real de un protocolo muy ligero,
que consuma muy poco ancho de banda y que permita comunicarse a través de la
publicación/suscripción para tener una comunicación bidireccional real con acuses de
recibo.

Esto permite que los dispositivos pasen de tener una iteración punto a punto a una iteración
más sofisticada donde se establezcan verdaderos diálogos entre las máquinas.

Aquí es donde entra en juego MQTT, un protocolo que permite eso: publicación y
suscripción de mensajes, comunicación bidireccional y acuses de recibo de dichos
mensajes.

2.1 ¿Qué es MQTT?


Como ya he comentado, MQTT es un protocolo M2M y son siglas en inglés, ​Message
Queue Telemetry Transport​. Está basado en un protocolo de mensajería
publicación/suscripción, al contrario que HTTP que es petición/respuesta.

7
Uno de sus puntos fuertes es que es extremadamente simple y ligero.

Por este motivo es muy interesante para sistemas que requieren poco ancho de banda,
tienen una alta latencia y requieren de poco consumo de los dispositivos.

Los objetivos del protocolo MQTT es minimizar el ancho de banda, comunicación


bidireccional entre dispositivos, minimizar los requerimientos de los dispositivos tanto
recursos como consumo y garantizar la fiabilidad y cierto grado de seguridad.

La latencia es el tiempo desde que se envía un mensaje hasta que llega a su destino.
Cuanto más tiempo, más latencia.

2.1.1 ¿Quién creó MQTT?


Al final, como sucede con casi todas las tecnologías, surgió por una necesidad. Los
ingenieros Dr. Andy Stanford-Clark de IBM y Arlen Nipper de Eurotech fueron los creadores
del protocolo MQTT.

En 1.999 estaban trabajando en la construcción de un oleoducto. De repente tenían la


necesidad de enviar datos a través de un protocolo de comunicaciones que optimizara el
ancho de banda y el consumo de las baterías.

Por aquel entonces para transmitir información desde un sitio remoto como un desierto, un
bosque o una montaña, tenías que hacer uso de la comunicación vía satélite. Este tipo de
comunicación era extremadamente caro en aquellos tiempos.

Ahora tenemos otras tecnologías como las redes ​LPWAN como SigFox o Lora. Pero en
1999 no había tantas posibilidades. Esto les llevó a crear el protocolo MQTT para un caso
concreto pero en la actualidad, se utiliza en infinidad de proyectos.

En comunicaciones máquina a máquina o M2M, dispositivos que utilizan tecnología IoT,


aplicaciones móviles con la necesidad de optimizar el ancho de banda y el consumo
eléctrico. Puedes ver un montón de proyectos en la​ ​web oficial de MQTT​.

2.1.2 ¿Es un estándar de comunicaciones?


Desde el año 2014 se ha convertido en un ​estándar OASIS​. Esta organización sin ánimo de
lucro, se orienta al desarrollo, la convergencia y la adopción de los estándares de comercio
electrónico y servicios web.

8
Es muy importante que un protocolo o una tecnología se convierta en un estándar. Esto
permite que los proyectos evolucionen de forma independiente a los protocolos o
tecnologías.

Los estándares ofrecen un alto grado de compatibilidad entre desarrollos, seguridad,


interoperabilidad y escalabilidad de los proyectos sin preocuparnos de los protocolos.

El ejemplo más claro es TCP/IP, un protocolo inventando en los años 70 y que a día de hoy
se sigue utilizando masivamente.

Además de ser un estándar, es de código abierto. La ​especificación del protocolo se ha


publicado abiertamente con una licencia libre. Fue en el año 2011 cuando las empresas IBM
y Eurotech donaron el código MQTT al proyecto Eclipse.

2.1.3 ¿Es un protocolo seguro?


Siempre debemos partir de la suposición que mientras que una máquina esté conectada a
Internet, no se puede garantizar la seguridad al 100%. Partiendo de este hecho, MQTT
soporta cifrado mediante SSL.

Por lo tanto, podemos enviar datos cifrados a través de la red utilizando este protocolo. Eso
sí, se debe pagar un precio.

Cuando se utiliza cifrado SSL se añade una sobrecarga a la red y los microcontroladores,
haciendo que MQTT ya no sea un protocolo tan ligero y simple.

2.2 Arquitectura MQTT


En esta sección haré un repaso rápido de cómo se estructura un sistema que utiliza el
protocolo MQTT. Hablaré de la arquitectura típica.

Lo primero es ver cómo se conectan los dispositivos. Utilizan una topología en estrella es
decir, todos los clientes se conectan directamente a un punto central que hace de servidor.
En MQTT este servidor se llama broker.

9
Topología en estrella

El Broker es la parte central de la arquitectura y todos los mensajes pasan por él.

2.2.1 Arquitectura publicación/suscripción de MQTT


Se trata de una arquitectura basada en eventos. Cada mensaje se envía a los receptores
que se hayan suscrito a una publicación concreta. El Broker se encarga de distribuir los
mensajes a los receptores.

El topic es el tema donde se suscriben los receptores para recibir el mensaje. Veamos un
ejemplo de una comunicación típica para entender el concepto de arquitectura
publicación/suscripción.

Un cliente se suscribe a un topic que es como el tema, a quién va dirigido el mensaje.


Podemos entenderlo como el asunto de un email. Un mensaje no tiene destinatario
concreto, puede haber uno, muchos o ninguno.

10
El emisor, el que envía el mensaje, no sabe a quién va dirigido dicho mensaje, sólo el
broker lo sabe. Cuando llega un nuevo mensaje se lo envía a aquellos que se han suscrito
al topic.

El mensaje puede ser cualquier cosa, una temperatura, un 1 o un 0, un texto, ... El formato
es totalmente libre, lo decide el programador y el tamaño máximo depende de la
implementación del protocolo MQTT y no de la especificación.

2.2.2 ¿Qué es un topic?


Como ya he comentado, el topic es el tema del mensaje, a quién va dirigido ese mensaje.
Es un concepto que tenemos que tener muy claro así que vamos a verlo con una analogía.

Imagínate una editorial que publica revistas sobre temas técnicos. Tiene dos categorías
principales: electrónica y programación.

Dentro de estas categorías, la editorial define unas subcategorías donde se tratan temas
más específicos. Para electrónica tiene placas de desarrollo y componentes. Para
programación tiene programación backend y programación frontend.

Por último, están las revistas que van destinadas a algo concreto.

Dentro de electrónica/placas de desarrollo hay dos revistas: una dedicada a Arduino y otra
al ESP8266.

En electrónica/componentes hay otras dos revistas: dedicadas a los sensores ​DHT11 y


DS18b20​.

En la categoría de programación ocurre lo mismo. Dentro de programación/programación


backend se publican dos revistas orientadas a Java y NodeJS. Por último en
programación/programación frontend se publican otras dos revistas centradas en ​JavaScript
y​ ​HTML​.

El resumen de esta organización sería el siguiente.

11
Por ejemplo, te puedes suscribir a la revista de Arduino y recibir sólo esa revista. Sin
embargo, si te suscribes a la categoría de placas de desarrollo, recibirás todas las revistas
de esa categoría: Arduino y ESP8266.

De igual forma, si te suscribes a programación recibirás todas las revistas: Java, NodeJS,
JavaScript y HTML.

Creo que el concepto de publicación/suscripción con un topic o tema queda claro.

Sin embargo, los topic de MQTT tienen su propia sintaxis. Por ejemplo, si quieres recibir
sólo la revista de Arduino tienes que suscribirte a ​/editorial maker/electrónica/placas
desarrollo/arduino​.

Todo esto es lo que veremos a continuación.

2.2.3 Sintaxis de los topic


El símbolo / es un separador de niveles. Siempre se pone para separar cada uno de los
niveles.

Cuando trabajamos con un dispositivo del IoT utilizamos otros nombres para los topic. Por
ejemplo, podríamos tener algo como esto para medir la temperatura:

● casa/salon/temperatura
● casa/cocina/temperatura

El primer topic hace referencia a la temperatura del salón y el segundo topic a la


temperatura de la cocina.

Además, existen comodines como el símbolo + y #.

12
El símbolo + se sustituye por cualquier nivel. Si por ejemplo nos queremos suscribir a todos
los topic de temperatura podemos hacerlo de la siguiente manera

casa/+/temperatura

El símbolo + se sustituirá por cada nivel que tenga como nivel superior casa y como nivel
inferior temperatura.

El símbolo # también es un comodín. Este símbolo cubre los niveles que estén por debajo.
Por ejemplo, si quieres suscribirte a todos los mensajes que se envían a casa sólo tienes
que hacer lo siguiente:

casa/#

El topic anterior nos enviará cualquier mensaje que se envíe a casa o a cualquier nivel que
esté por debajo.

Es como si te suscribes a todas las revistas de la editorial en el ejemplo anterior.

2.2.4 Estructura de un mensaje MQTT


Lo más importante dentro del protocolo MQTT son los mensajes. Se envían de forma
asíncrona es decir, no hay que esperar respuesta una vez que se envía un mensaje.

Cada mensaje consta de 3 partes:

● Encabezado fijo. Ocupa sólo 2 bytes y es obligatorio enviar esta parte en todos los
mensajes.
● Encabezado variable. Ocupa 4 bits y no es obligatorio que esté en todos los
mensajes.
● Mensaje o carga útil (del inglés ​payload)​ . Puede tener un máximo de 256 Mb aunque
en implementaciones reales el máximo es de 2 a 4 kB.

Cada bit del mensaje está estudiado cuidadosamente para que se consuma el menor ancho
de banda posible.

No hace falta aprender todo esto de memoria. Cuando utilizamos una librería o un software,
el ya se encarga de crear el mensaje según una configuración por nosotros.

De lo único que tenemos que preocuparnos es de la carga útil es decir, qué queremos
enviar al receptor.

13
2.2.5 ¿Cómo funciona la arquitectura MQTT?
Una de las características más importantes es que los clientes o nodos no dependen unos
de otros ya que no tienen conocimiento de quién está al otro lado. Puede incluso que no
haya nadie en el otro extremo.

Esto permite algo muy importante en proyectos de este tipo: la escalabilidad.

Al contrario de lo que ocurre con el protocolo HTTP, no hay que hacer una petición para
recibir información desde un cliente. Cada cliente MQTT abre una conexión permanente
TCP con el broker.

El Broker tiene la capacidad de hacer que los mensajes sean persistentes, guardando el
mensaje hasta que se conecte el cliente al que va dirigido. Te recuerdo que el broker es el
único que sabe quién está suscrito a un topic.

2.2.6 Servicio de Calidad o QoS


He hablado en varias ocasiones de que MQTT es un protocolo fiable. Eso se debe a que
tiene implementado un Servicio de Calidad o QoS (del inglés ​Quality of Service​). Este
servicio determina cómo se entrega el mensaje a los receptores.

El QoS se especifica en cada mensaje que se envía y puede haber 3 grados de calidad:

● QoS 0: como máximo una vez. Esto implica que puede que no se entregue.
● QoS 1: al menos una vez. Se garantiza la entrega pero puede que duplicados.
● QoS 2: exactamente una vez. Se garantiza que llegará una vez el mensaje.

Utilizar un grado de calidad u otro dependerá de la fiabilidad que queramos tener en nuestro
sistema. Eso sí, debes tener en cuenta que cuanta más calidad menor será el rendimiento.

Ahora que ya tenemos los conocimientos suficientes, vamos a poner en práctica todo esto
para montar nuestro sistema basado en el protocolo MQTT en una Raspberry Pi.

2.3 Instalación Mosquitto en Raspberry Pi


Para instalar MQTT en una Raspberry Pi voy a utilizar un servidor ampliamente conocido
como es​ ​Eclipse Mosquitto​.

14
Mosquitto es un mediador de mensajes que incluye el protocolo MQTT. Además es de
código abierto lo que supone una ventaja para los Makers ya que lo podemos utilizar sin
ningún tipo de problema.

Para que el protocolo MQTT esté en constante disponibilidad, es recomendable instalar el


broker en un servidor que esté siempre encendido. Tenemos diferentes opciones pero la
más interesante es Raspberry Pi por su bajo coste y consumo.

Vamos a ver los pasos necesarios para tener operativo nuestro broker MQTT en Raspberry
Pi.

Debes tener instalado Raspbian y recomendable la última versión. En la página web de la


Fundación Raspberry Pi​ tienes un tutorial paso a paso.

2.3.1 Instalación Mosquitto en Raspberry Pi


Si ya tienes experiencia con Raspberry Pi conocerás el comando ​apt-get​. Se trata de una
herramienta para gestionar paquetes instalables a través de la línea de comandos.

Desafortunadamente no podemos utilizar sólo esta herramienta para instalar Mosquitto


MQTT.

Esto es debido a que si lo hacemos, no nos instalará la última versión del software y nos
generará errores de compatibilidad de software.

Raspberry Pi tiene que estar conectada a Internet para poder instalar el broker MQTT
Mosquitto.

Abre una terminal en tu Raspberry Pi.

15
Lo primero es descargar la ​signing key o clave de firma utilizando el comando ​wget​. Este
comando descarga el fichero indicado como parámetro en el directorio en el que te
encuentras.

sudo wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key

16
Añadimos la clave en una lista para autenticar el paquete que vamos a descargar más
adelante.

sudo apt-key add mosquitto-repo.gpg.key

Luego tienes que ir al directorio ​/etc/apt/sources.list.d/​ utilizando el comando ​cd​.

cd /etc/apt/sources.list.d/

17
Después descargamos la lista de repositorios de Mosquitto con ​wget.​ Si tienes instalada la
versión Jessie de Raspbian utiliza este comando.

sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list

Si tienes instalada la versión Stretch utiliza este otro comando.

sudo wget http://repo.mosquitto.org/debian/mosquitto-stretch.list

18
Ahora, para no tener que estar constantemente poniendo el comando ​sudo​, escribimos lo
siguiente en la terminal para ser usuario ​root​.

sudo -i

Este paso no es obligatorio, pero si no lo haces tendrás que poner ​sudo en todos los
comandos que van a continuación.

Como ves, la shell cambia de aspecto. A partir de ahora ya no hace falta poner la palabra
sudo​ antes.

Actualizamos la lista de paquetes disponibles y sus versiones.

apt-get update

Esto puede tardar un rato así que ten paciencia.

19
20
Ejecuta el siguiente comando para instalar el broker Mosquitto.

apt-get install mosquitto

Con esto ya tendríamos el Broker Mosquitto instalado en nuestra Raspberry Pi. Ahora toca
instalar el cliente para hacer las pruebas.

2.3.2 Instalar cliente MQTT en Raspberry Pi


Este paso va a ser muy sencillo. Si todavía no has cerrado la terminal anterior sólo tendrás
que escribir el siguiente comando.

apt-get install mosquitto-clients

Recuerda que si no estás logueado como ​root​ tendrás que poner antes el comando ​sudo​.

21
En un momento dado te hará la siguiente pregunta "​Do you want to continue? (¿Quieres
continuar?)". Tienes que dar a la tecla "​y​" y después pulsas la tecla ​Enter​.

22
Con esto ya hemos terminado de instalar el broker y el cliente MQTT. Ahora vamos a probar
la instalación con un ejemplo.

2.3.3 Ejemplo con Mosquitto MQTT


Ahora mismo si tu Raspberry Pi está conectada a la red de tu casa, puedes crear un topic
accesible desde cualquier cliente MQTT que esté conectado al broker.

De momento, lo único que queremos es probar que todo está bien instalado así que lo
haremos sobre la misma Raspberry Pi.

Pero antes de continuar vamos a ver los dos comandos que vamos a utilizar del cliente
MQTT Mosquitto, ​mosquitto_sub​ y m
​ osquitto_pub​.

2.3.3.1 Comando mosquitto_sub


Este comando nos permite suscribirnos a un topic escuchando y mostrando por pantalla los
mensajes enviados a este topic. Puede ​tomar muchos parámetros pero nosotros nos vamos
a centrar en 4.

mosquitto_sub -h BROKER -t TOPIC

Donde:
● -h: indica que lo que viene después es el host.
● BROKER: host del broker MQTT. El host se refiere a la dirección IP o nombre de la
máquina en la red donde tenemos instalado el broker MQTT. En nuestro caso es la
IP de la Raspberry Pi. Si no pasamos este parámetro cogerá por defecto localhost.
● -t: indica que lo que viene después es el topic al que queremos suscribirnos.
● TOPIC: nombre del topic al que nos vamos a suscribir.

Los topic no hace falta crearlos en ningún sitio, ni en el broker MQTT. En el momento que
un cliente se suscribe a un topic que no existe, el broker lo detecta y cada vez que llegue
un mensaje a este topic, se lo enviará al cliente.

2.3.3.2 Comando mosquitto_pub


Con este comando podemos publicar mensajes muy simples. Como ocurre con
mosquitto_sub, ​puede tomar muchos parámetros​.

A continuación te explico los 6 parámetros más importantes de este comando.

mosquitto_pub -h BROKER -t TOPIC -m MENSAJE

23
Donde:
● -h: indica que lo que viene después es el host.
● BROKER: dirección IP o nombre de la máquina en la red donde tenemos instalado el
broker Mosquitto.
● -t: indica que lo que viene después es el topic al que queremos enviar el mensaje.
● TOPIC: nombre del topic al que vamos a enviar el mensaje.
● -m: indica que lo que viene después es el mensaje.
● MENSAJE: el mensaje que queremos enviar. Tiene que ir entre comillas dobles (").
Por ejemplo "Temperatura = 25ºC" o simplemente “25”. Tenemos total libertad en
este sentido.

Ahora vamos a probar el protocolo MQTT enviando unos mensajes.

2.3.4 Primera prueba con el protocolo MQTT


Para hacer la primera prueba vamos a utilizar dos terminales de Raspberry Pi. Abre dos
ventanas como se muestra a continuación.

Haremos que una ventana sea el emisor y otra el receptor. Elige la que quieras y escribe el
siguiente comando.

mosquitto_sub -h localhost -t casa/comedor/temperatura

24
Esta ventana será el receptor y lo que acabamos de hacer es suscribirnos al topic
casa/comedor/temperatura​. La terminal se queda esperando a recibir algún mensaje.

En el otro terminal escribe el siguiente comando que envía un mensaje al topic


casa/comedor/temperatura​.

mosquitto_pub -h localhost -t casa/comedor/temperatura -m "Temperatura:


25ºC"

Ahora si te fijas en la terminal que hace de receptor, verás que ha llegado un mensaje
nuevo.

25
Cómo ves es muy sencillo crear una comunicación con el protocolo MQTT. Puedes seguir
probando. Envía mensajes y utiliza otros topic. También puedes utilizar los comodines que
hemos visto anteriormente: + y #.

Por último, es aconsejable que nuestra Raspberry Pi tenga siempre la misma IP. A esto se
le llama IP estática o fija.

Así, aunque la Raspberry Pi se apague o se desconecte de la red, cuando vuelva a


conectarse tenga la misma IP. Esto nos ahorrará un montón de trabajo como veremos más
adelante.

2.3.5 Configurando una IP fija en Raspberry Pi


Vamos a ver los pasos que tenemos que seguir para la Raspberry Pi tenga una IP fija. Los
pasos que se detallan a continuación son sólo válidos para la última versión de Raspbian
que cuando estoy escribiendo estas líneas es la 4.4.34

Lo primero que tenemos que hacer es abrir una terminal y escribir el siguiente comando.

ifconfig

Esto te mostrará algo parecido a la siguiente imagen.

26
La primera parte, donde pone ​eth0 nos muestra la configuración de red cuando nos
conectamos a través de un cable ​ethernet​.

La parte donde pone ​wlan0 es donde nos muestra la configuración de red cuando nos
conectamos a través de la red WiFi.

En mi caso, tengo conectada la Raspberry Pi vía WiFi. Por eso aparecen los datos de IP,
puerta de enlace y máscara.

Debes quedarte con el nombre de la interfaz WiFi y ethernet. En mi caso es ​eth0​ y ​wlan0​.

27
Además de estos parámetros, tenemos que conocer la IP del router o ​gateway​. Esto lo
podemos saber abriendo una terminal y escribiendo el siguiente comando.

route -n

Aparecerá algo parecido a la siguiente imagen.

Apunta la IP de tu ​gateway​. En mi caso es la 192.168.0.1.

Ahora ya tenemos todo lo necesario para establecer una IP fija en la Raspberry Pi. Para
hacer esto tenemos que editar el fichero que se encuentra en ​/etc/dhcpcd.conf​.

Escribe el siguiente comando en una terminal.

sudo nano /etc/dhcpcd.conf

Esto abrirá el editor ​nano ​donde podremos modificar este fichero.

28
Baja hasta el final con el cursor. Es como si estuvieras trabajando con un editor de textos.

Ahora vamos a modificar este fichero y vamos a poner lo siguiente

29
interface eth0

static ip_address=192.168.0.167/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1

interface wlan0

static ip_address=192.168.0.167/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1

Lo primero es poner la ​interface que vamos a configurar. Si estás seguro que sólo vas a
conectar tu Raspberry Pi por WiFi o por ethernet, sólo tendrás que configurar esa ​interface​.

Yo recomiendo configurar las dos por si acaso en algún momento cambias de ​interface​.

static ip_address: aquí pondremos la dirección IP que queremos configurar cómo estática.
Asegúrate de poner al final /24.

static routers:​ es la dirección IP del ​router​ o ​gateway​, la que hemos obtenido antes.

static domain_name_servers: es la dirección IP de su DNS (normalmente coincide con el


router​).

Como puedes comprobar, he modificado la IP y he puesto la 192.168.0.167 en vez de la


192.168.0.171. Puedes utilizar la misma pero en este ejemplo he decidido cambiar de IP
para mostrarte cómo averiguar si una IP está libre o no.

Mucho ojo con esto ya que podríamos tener un conflicto de IPs. Para asegurarnos que la IP
está libre sólo tenemos que hacer un ​ping​ a la IP que queremos utilizar.

Abre una terminal y escribe lo siguiente.

ping 192.168.0.167

Sustituye la IP por la que quieras asignar. Si el resultado es ​Host Unreachable quiere decir
que la IP está libre y por lo tanto la podemos utilizar.

30
Para salir sólo tienes que pulsar a la vez CTRL + C

Si el resultado es positivo mostrará el tiempo que ha tardado en hacer el ​ping​. En este caso
no podrás utilizar esa IP.

Ahora que estamos seguros que vamos a utilizar una IP que no está siendo utilizada por
otro dispositivo, podemos modificar el archivo.

Vuelve a la terminal donde tenemos abierto el editor ​nano con el archivo ​/etc/dhcpcd.conf y
escribe lo que habíamos visto antes.

31
Asegúrate que has escribo bien todo.

Para salir del editor pulsa CTRL + X

32
Para guardar los cambios pulsa la letra ​Y​.

Por último pulsa la tecla ​Enter y ya estarán guardados los datos. Ahora sólo nos queda
reiniciar la Raspberry Pi.

Una vez arranque, si vuelves a escribir el comando ​ifconfig en una terminal te mostrará la IP
estática que acabamos de configurar.

33
Ahora vamos a trabajar en el lado del cliente con NodeMCU. Enviaremos y recibiremos
datos desde la Raspberry Pi.

2.4 Mensajes con MQTT


En esta parte del libro vamos a empezar a trabajar con NodeMCU. Se trata de una placa de
desarrollo o prototipado basada en ESP8266.

La puedes encontrar en muchos sitios y el precio ronda los ​8€​. También puedes utilizar
cualquier otra placa basada en el ESP8266 como la Wemos, que viene a costar más o
menos lo mismo, ​8€​.

34
Antes de continuar, te recomiendo que leas el artículo ​tutorial paso a paso con NodeMCU y
cómo programar NodeMCU desde el IDE de Arduino​. Es necesario tener listo tanto el IDE
como la placa de desarrollo.

Ahora sí, ya podemos empezar a trabajar con NodeMCU y MQTT. Lo primero será instalar
la librería.

2.4.1 Instalando la librería PubSubClient


Una de las grandes ventajas que tenemos a la hora de prototipar con Arduino o ESP8266,
es que tenemos un montón de librerías que nos hacen la vida mucho más fácil.

Si no tienes experiencia con librerías, te aconsejo que eches un vistazo al tutorial donde
explico cómo​ ​instalar librerías en el IDE de Arduino​.

PubSubClient es una librería compatible con Arduino y ESP8266. Básicamente hace que
nuestra placa se comporte como un cliente MQTT es decir, que podamos publicar mensajes
y suscribirnos a un topic o varios para recibir mensajes.

Da lo mismo si utilizas un Arduino o un ESP8266, el código es prácticamente el mismo. La


diferencia reside en cómo nos conectamos a la red WiFi, cada placa utiliza su propia
librería.

Lo primero es instalar la librería. Abre la opción del menú ​Programa>Incluir Librería>Gestor


de librerías​ y busca PubSubClient

35
Haz ​click en instalar y listo, ya tienes el la librería instalada en tu ordenador y preparada
para ser utilizada.

2.4.2 Enviando un mensaje a través del protocolo MQTT con NodeMCU


Vamos a partir de uno de los ejemplos que vienen dentro de la librería. Lo encontrarás en
Archivo>Ejemplos>PubSubClient>mqtt_esp8266

Este sería el código de este ejemplo.

/*
Basic ESP8266 MQTT example

This sketch demonstrates the capabilities of the pubsub library in


combination
with the ESP8266 board/library.

It connects to an MQTT server then:


- publishes "hello world" to the topic "outTopic" every two seconds
- subscribes to the topic "inTopic", printing out any messages
it receives. NB - it assumes the received payloads are strings not
binary
- If the first character of the topic "inTopic" is an 1, switch ON the
ESP Led,
else switch it off

36
It will reconnect to the server if the connection is lost using a
blocking
reconnect function. See the 'mqtt_reconnect_nonblocking' example for
how to
achieve the same result without blocking the main loop.

To install the ESP8266 board, (using Arduino 1.6.4+):


- Add the following 3rd party board manager under "File -> Preferences
-> Additional Boards Manager URLs":
http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Open the "Tools -> Board -> Board Manager" and click install for the
ESP8266"
- Select your ESP8266 in "Tools -> Board"

*/

​ ESP8266WiFi.h>
#include <
#include <​ PubSubClient.h>

// Update these with values suitable for your network.

​ har​* ssid = ​"........"​;


const​ c
const​ c​ har​* password = ​"........"​;
const​ c ​ har​* mqtt_server = ​"broker.mqtt-dashboard.com"​;

WiFiClient espClient;
PubSubClient ​client​(espClient);
long​ lastMsg = ​0​;
char​ msg[​50​];
int​ value = ​0​;

void​ ​setup​() {
pinMode(BUILTIN_LED, OUTPUT); ​// Initialize the BUILTIN_LED pin as
an output
Serial.begin(​115200​);
setup_wifi();
client.setServer(mqtt_server, ​1883​);
client.setCallback(callback);
}

void​ ​setup_wifi​() {

37
delay(​10​);
​// We start by connecting to a WiFi network
Serial.println();
Serial.print(​"Connecting to "​);
Serial.println(ssid);

WiFi.begin(ssid, password);

​while​ (WiFi.status() != WL_CONNECTED) {


delay(​500​);
Serial.print(​"."​);
}

Serial.println(​""​);
Serial.println(​"WiFi connected"​);
Serial.println(​"IP address: "​);
Serial.println(WiFi.localIP());
}

void​ ​callback​(​char​* topic, byte* payload, ​unsigned​ ​int​ length) {


Serial.print(​"Message arrived ["​);
Serial.print(topic);
Serial.print(​"] "​);
​for​ (​int​ i = ​0​; i < length; i++) {
Serial.print((​char​)payload[i]);
}
Serial.println();

​// Switch on the LED if an 1 was received as first character


​if​ ((​char​)payload[​0​] == ​'1'​) {
digitalWrite(BUILTIN_LED, LOW); ​// Turn the LED on (Note that LOW
is the voltage level
​// but actually the LED is on; this is because
​// it is acive low on the ESP-01)
} ​else​ {
digitalWrite(BUILTIN_LED, HIGH); ​// Turn the LED off by making the
voltage HIGH
}

​ econnect​() {
void​ r
​// Loop until we're reconnected

38
​while​ (!client.connected()) {
Serial.print(​"Attempting MQTT connection..."​);
​// Attempt to connect
​if​ (client.connect(​"ESP8266Client"​)) {
Serial.println(​"connected"​);
​// Once connected, publish an announcement...
client.publish(​"outTopic"​, ​"hello world"​);
​// ... and resubscribe
client.subscribe(​"inTopic"​);
} ​else​ {
Serial.print(​"failed, rc="​);
Serial.print(client.state());
Serial.println(​" try again in 5 seconds"​);
​// Wait 5 seconds before retrying
delay(​5000​);
}
}
}

void​ ​loop​() {

​if​ (!client.connected()) {
reconnect();
}
client.loop();

​long​ now = millis();


​if​ (now - lastMsg > ​2000​) {
lastMsg = now;
++value;
​snprintf​ (msg, ​75​, ​"hello world #%ld"​, value);
Serial.print(​"Publish message: "​);
Serial.println(msg);
client.publish(​"outTopic"​, msg);
}
}

Vamos a ir viendo las modificaciones que tenemos que hacer para enviar un mensaje con el
protocolo MQTT desde NodeMCU.

En esta parte vamos a poner los datos de la red WiFi, ssid y contraseña, y la IP del broker
MQTT que coincide con la IP de nuestra Raspberry Pi.

39
Como ya sabemos cuál es, no hará falta entrar de nuevo a la Raspberry Pi, aún así, puedes
confirmarlo ejecutando el siguiente comando.

ifconfig

Esto te mostrará algo parecido a lo siguiente.

En mi caso, la IP de mi Raspberry Pi sigue siendo 192.168.0.167, cómo era de prever.

Cambia el siguiente código en el IDE de Arduino.

​ har​* ssid = ​"WIFILUIS"​;


const​ c
const​ c​ har​* password = ​"123456"​;
const​ c ​ har​* mqtt_server = ​"192.168.0.167"​;

La variale ​ssid almacena el nombre de tu red WiFi, la variable password la contraseña y la


variable ​mqtt_server ​es la IP que acabamos de obtener, cada uno pondrá la suya.

La red a la que se conecte NodeMCU debe ser la misma que la que tienes configurada en
la Raspberry Pi para poder enviar mensajes entre estos dos dispositivos.

40
Vamos a comenzar cambiando los topic que vienen por defecto. El esquema de nuestra red
MQTT será el siguiente:

Antes de continuar déjame que te explique este esquema. El nivel superior es la casa. De
aquí partirán el resto de niveles.

En este caso sólo tenemos uno, el despacho, pero podríamos tener debajo de casa la
cocina, el salón o cualquier otra habitación.

Del despacho salen dos subniveles: luz y temperatura. De aquí podríamos sacar dos topic
para acceder a los datos de la luz y de la temperatura.

● casa/despacho/luz
● casa/despacho/temperatura

Ahora te preguntarás ¿qué datos se envía al topic de la luz y de la temperatura? Aquí es


donde cobra sentido la frase: ​protocolo basado en eventos.​

Cuando un dispositivo se suscribe a un topic recibirá información que, dependiendo de lo


que sea, ejecutará una u otra cosa es decir, se producirá un evento.

Por ejemplo, el dispositivo que se suscriba al topic de ​casa/despacho/luz podrá encender y


apagar una luz.

Sin embargo, el dispositivo que se suscriba al topic de ​casa/despacho/temperatura podrá


recibir datos de temperatura. Con esa temperatura podemos hacer varias cosas, mostrarla
en gráfico, activar o desactivar algo según la temperatura, etc…

41
Panel de control Acuario con Node-RED, Wemos Mini D1 y protocolo MQTT

Lo que quiero decir es que el topic está muy relacionado con lo que puede hacer el
dispositivo que se suscribe.

Si un dispositivo va a recibir los datos de la luz, este deberá estar dotado de algún relé o
algún sistema de iluminación que podamos encender o apagar. Por ejemplo un ESP8266
con un relé.

Al igual que el dispositivo que reciba los datos de temperatura tendrá que tener una
memoria para almacenar los datos y la posibilidad de mostrarlo en alguna pantalla en
formato gráfico. Por ejemplo una Raspberry Pi.

Sólo quería aclarar y hacerte ver que los topic son como accionadores, el dispositivo que
reciba un mensaje de ese topic tendrá que tener los componentes necesarios para llevar a
cabo esa acción.

Tras este paréntesis continuemos.

En el topic ​casa/despacho/luz ​se publicarán dos datos:

42
● 1: cuando se reciba cambiará el estado de un pin digital para encender un LED.
● 0: cuando se reciba cambiará el estado de un pin digital para apagar un LED.

La placa NodeMCU estará suscrita a este topic y encenderá o apagará un LED cuando
reciba el mensaje correspondiente.

En el topic ​casa/despacho/temperatura se publicará la temperatura. La Raspberry Pi estará


suscrita a ese topic y recibirá la información.

Recuerda que hemos instalado el cliente Mosquitto.

Vamos a empezar por NodeMCU cambiando el topic que envía y el que recbie. Ves a la
línea 98 y sustituye esto

client.publish(​"outTopic"​, ​"hello world"​);

por esto

client.publish(​"casa/despacho/temperatura"​, ​"Enviando el primer


mensaje"​);

En esta línea estamos diciendo que publique un mensaje (​Enviando el primer mensaje​) en
el topic ​casa/despacho/temperatura​.

Luego en la línea 100 sustituye esto

client.subscribe(​"inTopic"​);

por esto

client.subscribe(​"casa/despacho/luz"​);

En esta línea estamos diciendo que se suscriba al topic ​casa/despacho/luz​.

Sólo nos falta cambiar la línea 124. Sustituye esto

client.publish(​"outTopic"​, msg);

por esto

43
client.publish(​"casa/despacho/temperatura"​, msg);

Con estos cambios ya tenemos todo preparado para enviar nuestro primer mensaje con el
protocolo MQTT desde NodeMCU.

A continuación te dejo el código completo que tienes que cargar en la placa.

/*
Basic ESP8266 MQTT example

This sketch demonstrates the capabilities of the pubsub library in


combination
with the ESP8266 board/library.

It connects to an MQTT server then:


- publishes "hello world" to the topic "outTopic" every two seconds
- subscribes to the topic "inTopic", printing out any messages
it receives. NB - it assumes the received payloads are strings not
binary
- If the first character of the topic "inTopic" is an 1, switch ON the
ESP Led,
else switch it off

It will reconnect to the server if the connection is lost using a


blocking
reconnect function. See the 'mqtt_reconnect_nonblocking' example for
how to
achieve the same result without blocking the main loop.

To install the ESP8266 board, (using Arduino 1.6.4+):


- Add the following 3rd party board manager under "File -> Preferences
-> Additional Boards Manager URLs":
http://arduino.esp8266.com/stable/package_esp8266com_index.json
- Open the "Tools -> Board -> Board Manager" and click install for the
ESP8266"
- Select your ESP8266 in "Tools -> Board"

*/

​ ESP8266WiFi.h>
#include <
#include <​ PubSubClient.h>

44
// Update these with values suitable for your network.

​ har​* ssid = ​"........"​;


const​ c
const​ c​ har​* password = ​"........"​;
const​ c ​ har​* mqtt_server = ​"broker.mqtt-dashboard.com"​;

WiFiClient​ espClient;
PubSubClient client(espClient);
long​ lastMsg = ​0​;
char​ msg[​50​];
int​ value = ​0​;

void​ ​setup​() {
​pinMode​(BUILTIN_LED, ​OUTPUT​); ​// Initialize the BUILTIN_LED pin as
an output
​Serial​.​begin​(​115200​);
setup_wifi();
client.setServer(mqtt_server, ​1883​);
client.setCallback(callback);
}

void​ setup_wifi() {

​delay​(​10​);
​// We start by connecting to a WiFi network
​Serial​.​println​();
​Serial​.​print​(​"Connecting to "​);
​Serial​.​println​(ssid);

​WiFi​.​begin​(ssid, password);

​while​ (​WiFi​.status() != WL_CONNECTED) {


​delay​(​500​);
​Serial​.​print​(​"."​);
}

​Serial​.​println​(​""​);
​Serial​.​println​(​"WiFi connected"​);
​Serial​.​println​(​"IP address: "​);
​Serial​.​println​(​WiFi​.​localIP​());
}

void​ callback(​char​* topic, ​byte​* payload, ​unsigned​ ​int​ length) {

45
​Serial​.​print​(​"Message arrived ["​);
​Serial​.​print​(topic);
​Serial​.​print​(​"] "​);
​for​ (​int​ i = ​0​; i < length; i++) {
​Serial​.​print​((​char​)payload[i]);
}
​Serial​.​println​();

​// Switch on the LED if an 1 was received as first character


​if​ ((​char​)payload[​0​] == ​'1'​) {
​digitalWrite​(BUILTIN_LED, ​LOW​); ​// Turn the LED on (Note that LOW
is the voltage level
​// but actually the LED is on; this is because
​// it is acive low on the ESP-01)
} ​else​ {
​digitalWrite​(BUILTIN_LED, ​HIGH​); ​// Turn the LED off by making the
voltage HIGH
}

void​ reconnect() {
​// Loop until we're reconnected
​while​ (!client.​connected​()) {
​Serial​.​print​(​"Attempting MQTT connection..."​);
​// Attempt to connect
​if​ (client.​connect​(​"ESP8266Client"​)) {
​Serial​.​println​(​"connected"​);
​// Once connected, publish an announcement...
client.publish(​"casa/despacho/temperatura"​, ​"Enviando el primer
mensaje"​);
​// ... and resubscribe
client.subscribe(​"casa/despacho/luz"​);
} ​else​ {
​Serial​.​print​(​"failed, rc="​);
​Serial​.​print​(client.state());
​Serial​.​println​(​" try again in 5 seconds"​);
​// Wait 5 seconds before retrying
​delay​(​5000​);
}
}
}
void​ ​loop​() {

46
​if​ (!client.​connected​()) {
reconnect();
}
client.​loop​();

​long​ now = ​millis​();


​if​ (now - lastMsg > ​2000​) {
lastMsg = now;
++value;
snprintf (msg, ​75​, ​"hello world #%ld"​, value);
​Serial​.​print​(​"Publish message: "​);
​Serial​.​println​(msg);
client.publish(​"casa/despacho/temperatura"​, msg);
}
}

Ahora vamos a la Raspberry Pi y ejecutamos el siguiente comando en una terminal para


suscribirnos al topic ​casa/despacho/temperatura

mosquitto_sub -h localhost -t casa​/despacho/​temperatura

Si ya has cargado el código en la placa verás los mensajes que se están recibiendo en la
terminal de Raspberry Pi.

47
Estos mensajes los está mandando NodeMCU. Ahora vamos a enviar un mensaje desde la
Raspberry Pi a NodeMCU.

Abre otro terminal y escribe el siguiente comando.

mosquitto_pub -h localhost -t casa​/despacho/​luz -m ​0

Si el LED que viene incorporado en la placa estaba encendido, se apagará.

Si escribes este otro comando

mosquitto_pub -h localhost -t casa​/despacho/​luz -m ​1

Encenderás el LED. Así de sencillo :)

Con esto hemos terminado la parte del protocolo MQTT. Ahora veremos cómo integrar todo
esto con Node-RED.

48
3 Node-RED
Node-RED es una herramienta de programación que nos permite conectar diferentes placas
de hardware, APIs y servicios de una forma muy sencilla.

Su fuerte es el editor web donde podemos construir nuestra aplicación a base de nodos y
conexiones entre ellos.

Se trata de un híbrido entre la programación visual, tipo Snap! o Scratch, y la programación


con código en JavaScript.

Está construido sobre ​NodeJS​, un framework que se ejecuta en un ordenador y hace


funcionar a la máquina como un servidor.

Es de código abierto y multiplataforma. Está basado en JavaScript que se ejecuta en el


propio servidor y no en el navegador, como estamos acostumbrados a ver funcionar ese
lenguaje.

49
No te asustes, no veremos nada de NodeJS. Además, la programación en JavaScript es
muy sencilla y no requiere tener grandes conocimientos.

Con sólo saber programar en C, C++ o código nativo de Arduino, es más que suficiente.

Por lo tanto, Node-RED nos permite conectar nuestras placas Arduino o ESP8266 a
diferentes servicios y APIs.

Irás viendo a lo largo de esta guía práctica los pasos para poder controlar un pin digital con
una placa NodeMCU desde una página web.

Además, veremos cómo mostrar información en esa página web sin escribir ni una línea de
código en HTML o CSS.

Eso sí, esto no es una guía de Node-RED, sólo es un acercamiento a esta maravillosa
herramienta a través de un ejercicio práctico. Node-RED es una herramienta muy extensa
que sirve para muchas cosas.

Empecemos por el principio, instalando Node-RED en una Raspberry Pi.

3.1 Instalando Node-RED en Raspberry Pi


Para seguir esta guía debes tener instalada la última versión de Raspbian. La puedes
encontrar en la web de la fundación ​RaspberryPi.org​.

Cuando instalas la última versión, Node-RED ya viene preinstalado. Aunque podríamos


utilizarlo, es recomendable actualizar NodeJS.

50
Escribe el siguiente parámetro en un terminal.

bash <(curl -sL


https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/r
esources/update-nodejs-and-nodered)

En un momento dado te preguntará si estás seguro de hacer esto. Pon ​Y de yes (si) y le das
al enter.

Lo que sucede a continuación puede tardar entre 20 o 30 minutos así que ten paciencia. Al
final, obtendrás un resultado parecido a esto.

51
3.1.1 Ejecutando Node-RED
Te voy a enseñar cómo ejecutar y apagar Node-RED por si lo tienes que hacer en algún
momento. Lo ideal es que se ejecute automáticamente cuando se inicie Raspbian.

Puedes ejecutar Node-RED de dos formas diferentes.

La primera sería desde en la opción del ​Menú>Programación>Node-RED

52
Esto abrirá una terminal y aparecerá algo parecido a la siguiente imagen:

Si cierras la terminal, Node-RED seguirá ejecutándose.

53
La segunda forma de arrancar Node-RED es ejecutar el siguiente comando.

node-red-start

El resultado es el mismo a cuando lo hacemos desde la opción del menú.

Para parar Node-RED tienes que escribir este otro comando.

node-red-stop

Y obtendrás un resultado parecido a la siguiente imagen.

3.1.2 Ejecución automática de Node-RED con Raspbian


Como ya te he comentado, lo ideal es que Node-RED se arranque de forma automática con
Raspbian.

Eso lo hacemos ejecutando el siguiente comando.

sudo systemctl enable nodered.service

54
Este comando no produce ningún resultado. Puedes comprobar que ahora Node-RED se
ejecuta de forma automática si reinicias Raspberry Pi e intentas acceder al editor.

Si no sabes acceder al editor, en el siguiente apartado de explico cómo.

3.2 Accediendo al editor


Para empezar a crear nuestro primer proyecto tenemos que acceder al editor web.
¿Recuerdas la IP estática que hemos configurado? Pues necesitamos esa IP. Ahora
entiendes porque es tan importante establecer una IP fija :)

Abre un navegador y escribe lo siguiente ​http://IP-RASPBERRY-PY:1880/

Sustituye ​IP-RASPBERRY-PY por la IP de tu Raspberry Pi. Por ejemplo, yo me tengo que


conectar a esta dirección:

http://192.168.0.167:1880

Puedes acceder desde cualquier ordenador que esté en la misma red, no hace falta que sea
desde la propia Raspberry Pi.

Si tienes un ordenador portátil o de sobremesa, puedes entrar a Node-RED desde el


navegador web de cualquier ordenador.

Lo primero que encuentras cuando entras es el editor son 3 bloques.

55
Los nodos ordenados por módulos, el área de trabajo con los flows o flujos y los paneles de
opciones.

Vamos a ver cada uno de ellos más detenidamente.

3.2.1 Nodos
Los nodos son iconos que se arrastran al área de trabajo y se conectan entre sí. Cada nodo
ofrece una funcionalidad diferente que puede ir desde depurar lo que está sucediendo en un
flujo hasta almacenar en una base datos información.

Por ejemplo, podemos tener un flujo de nodos que cada vez que llegue un mensaje MQTT a
un topic nos muestre la información en un panel de control.

En este ejemplo podemos ver cómo se reciben los datos de temperatura y humedad vía
MQTT.

Hay una gran variedad de nodos. Además de los que vienen instalados por defecto
podemos instalar nodos nuevos.

Están agrupados según su funcionalidad.

56
● Input​: son nodos para adquisición de datos. Podemos suscribirnos a un topic MQTT
o recibir una petición HTTP.
● otuput​: son nodos que nos permiten enviar datos por ejemplo, publicar en un topic
MQTT, acceder a un link, hacer una llamada HTTP o conectar con servicios como
IFTTT.
● function​: son nodos que pueden implementar una lógica concreta o que nos permite
programar en JavaScript. Por ejemplo hay un nodo ​delay ​que hace una pausa o un
nodo ​function ​que te permite programar una funcionalidad específica.
● social​: estos nodos permiten conectarse con redes sociales o enviar emails.
● Raspberry Pi​: nodos específicos para Raspberry Pi como acceder a los pines GPIO
o acceder al teclado o ratón.

No es necesario aprenderse de memoria todos los nodos, con conocer los grupos es
suficiente.

Te recomiendo que vayas conociendo cada nodo según los vayas utilizando. En el panel de
nodos existe un campo de búsqueda que filtra por nombre.

Esto nos ayuda a buscar el nodo adecuado. Lo único que tienes que tener en cuenta es que
sólo entiende inglés.

Imagínate que quieres reproducir un sonido en un momento dado. Sólo tienes que ir al filtro
y buscar ​audio​ por ejemplo.

57
Aparece un nodo en el grupo de ​output (salida) que dice ​play audio​. Si quieres saber qué
hace puedes hacer click sobre el nodo y te muestra más información.

3.2.2 Paneles de información


En la parte derecha de Node-RED tenemos los paneles de información. Estos paneles irán
variando dependiendo del nodo o grupo de nodos con los que estemos trabajando.

58
Por defecto tenemos dos.

El panel de info nos da información de diferente tipo. Si tenemos seleccionado un flujo nos
da información sobre el flujo o de un nodo o grupos de nodos.

El panel debug nos da información de lo que está sucediendo en el flujo. Es como el monitor
serie del IDE de Arduino.

A través del nodo ​debug ​podemos mostrar información en este panel.

59
3.2.3 Área de trabajo de flujos (flows)
El área de trabajo se divide en flujos. Cada flujo podemos decir que es un hilo de ejecución.
Se separan en pestañas y en la parte derecha tienes un símbolo + que te permite añadir
más flujos.

Dentro de cada flujo iremos añadiendo los nodos y las conexiones entre ellos. Para
entenderlo mejor vamos a hacer nuestro primer flujo.

3.3 Primer flujo de trabajo


En la lista de nodos busca y añade el nodo ​input>inject y el nodo ​output>debug ​y los
conectas entre sí.

60
Para añadir un nuevo nodo sólo tienes que arrastrar y soltar sobre el área de trabajo del
flujo.

Para conectarlos sólo tienes que hacer click sobre el punto final del nodo ​inject ​(azul) y sin
soltar llevarlo hasta el punto inicial del nodo ​debug ​(verde).

Esto genera una conexión entre esos dos nodos. Las conexiones nos permiten enviar datos
de un nodo a otro.

61
Si te fijas bien, los nodos de entrada o input sólo tienen un punto o círculo en el lado
derecho y los nodos de salida o output sólo tienen un punto o círculo en el lado izquierdo.

Esto es debido a su naturaleza, los nodos de entrada obtienen datos fuera de Node-RED y
los nodos de salida sacan datos de Node-RED.

En el momento que añades un nuevo nodo a un flujo, el botón que hay arriba a la derecha
que pone ​Deploy ​se activa y pasa a estar en un color rojo.

Este botón sirve para “​compilar​” la aplicación es decir, nos está indicando que ha habido
algún cambio en el flujo y necesita ser actualizado.

Viene a ser como el botón subir el código a la placa en el IDE de Arduino.

Si haces click en el botón Deploy, verás una alerta que te indica que la actualización
(deploy) se ha hecho correctamente.

62
Además el botón ​Deploy ​se vuelve a poner en color gris. Eso nos indica que la última
versión del flujo está cargada.

Para comprobar que el flujo que hemos creado funciona correctamente, pulsa en el nodo
inyect ​(azul) en la pestaña que tiene en la parte izquierda.

Aparecerá una alerta que nos está diciendo que se ha inyectado un ​timestamp o marca
temporal​.

Si abres el panel ​debug ​comprobarás cómo han aparecido unos números. Es la hora actual
en un formato especial, el timestamp. Nos dice los milisegundos que han pasado desde el 1
de enero del año 1970.

Ahora vamos a modificar las opciones de un nodo. Cada nodo tiene sus propias opciones y
para acceder a ellas sólo tienes que hacer doble click sobre el nodo en cuestión.

Haz doble click sobre el nodo que ponen timestamp.

63
Cuando haces esto ocurren varias cosas. Lo primero es que el nodo con el que estás
trabajando se resalta con un borde naranja.

Además, se abre un nuevo panel donde podemos modificar las opciones del nodo. Cada
nodo tiene sus propias opciones. Estas serían las del nodo ​inject​ del grupo ​input​.

64
Ahora vamos a cambiar el mensaje que envía el nodo ​inyect ​(azul) y en vez de mostrar el
timestamp que muestre el típico “Hola Mundo !!!!” :)

Este nodo es muy útil ya que permite ejecutarse cada cierto intervalo de tiempo modificando
la propiedad ​Repeat​.

Lo suelo utilizar para ejecutar ciertas tareas como por ejemplo que busque qué tiempo va a
hacer y me lo envíe por Twitter antes de despertarme, jejejeje.

En este ejemplo vamos a hacer que cada 10 segundos envíe el texto ​Hola Mundo !! al nodo
debug​ para que lo muestre en el panel ​debug​.

3.3.1 Cambiar el payload o la carga útil


El payload es el mensaje que vamos a enviar al nodo que está conectado. Aún no lo he
dicho, pero un nodo puede estar conectado a varios nodos.

Esto quiere decir que del nodo ​inyect ​pueden salir varias conexiones a varios nodos. Todo
depende de la lógica que se quiera implementar.

65
Vamos a cambiar el payload de este nodo desde el panel de opciones.

Si haces click en la flecha justo al lado de donde pone timestamp se despliega una lista.
Aquí tenemos varias opciones pero la que nos interesa ahora mismo es la que pone string.

Al seleccionar esta opción se habilita un campo de texto donde nos permite escribir. Aquí
vamos a poner el texto que vamos a enviar al siguiente nodo.

66
Ahora vamos a cambiar la propiedad ​Repeat​. Esta propiedad nos permite ejecutar este
nodo cada cierto intervalo de tiempo.

Se puede hacer de tres formas:

● interval​: ejecuta el nodo cada cierto intervalo de tiempo.


● interval between times​: ejecuta el nodo cada cierto intervalo de tiempo entre unas
horas y ciertos días de la semana.
● at a specific time​: ejecuta el nodo a una hora y día concreto.

El objetivo es ejecutar el nodo cada 10 segundos así que seleccionamos la opción ​interval ​y
escribimos en el campo ​every​ el número 10. Luego seleccionamos ​seconds​.

67
Por último vamos a poner un nombre descriptivo al nodo. Eso se hace cambiando la
propiedad ​Name​. Sirve para identificar el nodo dentro del flujo de trabajo.

Ahora sólo nos queda dar al botón ​Done ​y ya estaría listo el nodo con el nuevo mensaje.

68
Al modificar un flujo es decir, añadir, eliminar o modificar nodos, se activa de nuevo el botón
de ​Deploy​.

Tenemos que volver a recargar el flujo como hemos hecho antes. Si le das a este botón y
luego haces click en el botón de de la izquierda del nodo ​inyect ​verás como aparece el
mensaje en el panel ​debug​.

Pero no sólo eso, como hemos configurado que cada 10 segundos aparezca el mensaje,
cada vez que pase ese tiempo se mostrará el mensaje en el panel ​debug​.

Y con esto terminamos el ​Hola mundo de Node-RED. Ahora vamos a pasar a algo más
serio, implementar un cliente de MQTT dentro de Node-RED.

3.4 MQTT y Node-Red


La idea es poder controlar el LED que está integrado dentro de la placa de NodeMCU con
un panel de control de Node-RED.

También veremos cómo monitorizar datos enviados desde NodeMCU a Node-RED. Estos
datos pueden ser una temperatura, presión, humedad o cualquier otro parámetro.

69
3.4.1 Instalando nodos en Node-RED
Node-RED viene con un conjunto básico de nodos instalados. Estos nodos nos permiten
hacer muchas cosas como hemos visto.

Sin embargo, hay cosas muy específicas que requieren de nodos complementarios. Por
ejemplo, mostrar en un panel de control datos a través de gráficos.

Estas funcionalidades extras se deben añadir a Node-RED instalando un nuevo módulo de


nodos. Se hace a través del editor.

Sólo tienes que ir al menú que se encuentra al lado del botón Deploy marcado con 3 rayas y
desplegarlo.

Luego selecciona la opción ​Manage palette​. Esto abrirá un nuevo panel que nos permitirá
gestionar los nodos ya existentes o instalar nuevos.

Podemos encontrar nodos de todo tipo: que se comunican con una base de datos, que
controlan tiras de NeoPixel, compatibilidad con diferentes placas, etc...

Nosotros nos vamos centrar en un grupo de nodos que nos permiten crear un panel de
control.

En ese panel de control tendremos un interruptor para encender o apagar el LED y un par
de gráficos que nos mostrarán la temperatura.

70
Cuando entras en ​Manage Pallette se abre un nuevo panel con dos pestañas. La pestaña
Nodes muestra un listado de nodos ya instalados donde puedes deshabilitar y desinstalar
cualquiera de ellos.

En la pestaña de ​Install ​puedes buscar nodos para instalarlos en tu instalación de


Node-RED. Sólo tienes que buscar poniendo una palabra clave en el campo ​search
modules​.

71
Justo debajo te indica cuantos módulos hay disponibles en el repositorio. Ahora vamos a
buscar lo siguiente: ​node-red-dashboard

Esto te dará como resultado un módulo de nodos que se llama ​node-red-dashboard.​ Sólo
tienes que dar al botón de ​install y estaría disponible para utilizar en el área de nodos del
editor.

Cuando le das a instalar aparece una alerta que nos dice que algunos nodos tienen
dependencias y que no pueden ser resueltas automáticamente. Esto se resuelve reiniciando
Node-RED.

72
En el caso de que el módulo que has instalado no funcione correctamente, tendrás que ir a
la Raspberry Pi, abrir un terminal y parar y arrancar Node-RED a través de los comandos
que ya hemos visto.

De momento, ​node-red-dashboard no requiere que reiniciemos Node-RED así que sólo


tienes que dar a ​Install​ y de forma automática se instala el grupo de nodos.

Puede tardar más o menos dependiendo de tu conexión a Internet.

Una vez que se instale aparecerá un mensaje parecido a este.

Para cerrar ​Manage Pallete ​haz click en el botón ​close​. Ahora puedes ir a la paleta de
nodos y comprobar si ha instalado un módulo nuevo donde pone ​dashboard.

73
Gracias a este grupo de nodos podremos crear nuestro panel de control basado en MQTT.
En la siguiente veremos cómo hacerlo.

3.4.2 Encendiendo y apagando el LED


Vamos a comenzar enviando mensajes de Node-RED a NodeMCU. Te recuerdo que la
placa basada en el ESP8266 está suscrita al topic ​casa/despacho/luz​.

Esto quiere decir que va a recibir todos los mensajes que se envíen desde cualquier cliente
a ese topic.

Lo que haremos será enviar al topic un 1 para que encienda el LED y un 0 para que lo
apague.

3.4.2.1 Nodo de salida MQTT


En la paleta de nodos busca un módulo que pone ​output​. Ahora selecciona un nodo donde
pone ​mqtt​. Arrástralo al área de trabajo.

74
Este nodo nos permite publicar mensajes en un topic. Recuerda que los nodos están
agrupados en módulos según su funcionalidad.

El módulo de ​output​ permite enviar datos fuera del servidor donde se encuentra Node-RED.

Si haces doble click sobre el nodo ​mqtt,​ aparecerán las opciones de ese módulo.

Dentro de las opciones podemos configurar varias cosas, vamos a ver cada una de ellas.

75
● Server​: desde esta opción configuramos un broker MQTT.
● Topic​: es el topic donde vamos a enviar el mensaje.
● QoS​: es la calidad del servicio. Puede ser 0, 1 o 2.
● Retain​: indica si el Broker tiene que retener el mensaje en caso de que los
receptores no estén conectados.

Lo primero que vamos a hacer es configurar el broker MQTT que hemos instalado en la
Raspberry Pi. Pulsa el botón de editar que está en la opción ​Server​.

76
Esto abrirá un nuevo panel para rellenar la información del broker. En este panel pondremos
un nombre descriptivo, como ​Broker Raspberry Pi​, y la IP del broker MQTT.

La IP es la misma que tiene la Raspberry Pi.

Ahora pulsa el botón ​Add y, automáticamente, en el panel de opciones del nodo ​mqtt ​que
hemos añadido al flujo, se seleccionará el broker que hemos creado.

77
Este broker se quedará guardado para poder utilizarlo en otros nodos y en otros flujos.

Ahora vamos con el topic donde debemos poner la ruta para publicar los mensajes.
Recuerda que NodeMCU está suscrito a ​casa/despacho/luz​.

También podemos poner el QoS, por ejemplo a 2 y Retain a ​true​. Luego le damos un
nombre descriptivo, Luz por ejemplo, y hacemos click en ​Done​.

Con esto ya tenemos nuestro primer nodo que publica un mensaje a través de MQTT.

78
Pero si lo dejamos así, no hará nada ya que no hay ningún evento dentro de Node-RED que
ejecute este nodo.

Además, no hemos puesto en ningún sitio que carga útil o payload (el 1 o 0 para encender o
apagar el LED).

Esto es lo que veremos a continuación.

3.4.2.2 Añadiendo el payload al mensaje


El payload o carga útil es el contenido útil que vamos a enviar. Es lo que hará que en el otro
extremo se ejecute una acción u otra.

Pero antes de meternos de lleno con este tema, debemos entender cómo funciona
Node-RED.

Cuando conectamos nodos, lo que hacemos es crear conexiones que nos permiten mandar
datos de un nodo a otro.

Dependiendo de esos datos, se ejecutará una acción u otra. Es como si fuera el hilo de
ejecución de un programa donde declaramos variables y luego, a través de sentencias de
control como los ​if, for, swtich​, etc… conducimos la ejecución por un lado u otro.

En Node-RED los datos se envían a través de objetos en JavaScript llamados ​msg​. ​No te
asustes, es muy sencillo. Un objeto es una instancia a una clase. No es más que una
variable muy especial.

Las variables normales almacenan datos de un sólo tipo, un entero positivo o negativo, un
número decimal o una letra.

Sin embargo, las clases almacenan una estructura de datos de diferentes tipos. Por
ejemplo, podemos crear una clase que se llame perro.

Esta clase puede contener varias variables donde se almacene el nombre, del tipo cadena,
la edad, del tipo entero, color del pelo, del tipo cadena, etc…

Perro
- string: nombre
- int: edad
- string: color pelo
- …

A estas variables dentro de una clase se les llama propiedades, pero no dejan de ser
variables agrupadas dentro de la clase.

79
Cuando declaramos una clase (a esto se le llama instanciar una clase), obtenemos un
objeto de esa clase.

Entonces, en Node-RED se pasa información de un nodo a otro a través de un objeto de


JavaScript que se llama ​msg​. Se trata de una clase interna de Node-RED.

Este objeto puede tener varias propiedades dependiendo del nodo que estés utilizando. En
muchas ocasiones el objeto ​msg ​contiene una propiedad que se llama ​payload es decir, la
carga útil del mensaje.

Aunque se llaman igual, no confundir el payload del mensaje MQTT del payload del objeto
de Node-RED, son cosas diferentes.

Muchos nodos utilizan esa propiedad para hacer algo concreto con su contenido. Ese es el
caso del nodo de salida ​mqtt​.

Cuando recibe datos de otro nodo, mira la propiedad payload y envía esos datos como
carga útil del mensaje MQTT.

Vamos a enviar el primer mensaje a través del nodo ​mqtt que hemos configurado. Como
hemos hecho en el “Hola Mundo” vamos a arrastrar un nodo ​inject​ del módulo ​input.

Luego lo conectamos con el nodo ​mqtt​.

Ahora sólo nos falta configurarlo haciendo doble click sobre el nodo ​inject​. En la opción
Payload​ dejamos ​timestamp​ y en ​Repeat ​ponemos que se envíe cada 10 segundos.

80
Al seleccionar ​timestamp en la opción ​Payload lo que hace es guardar en la propiedad
payload del objeto ​msg de Node-RED el tiempo calculado en timestamp es decir, estamos
enviando en esa propiedad un número.

Ahora haz click en ​Done para guardar los datos y por último no te olvides de dar a ​Deploy
para que los cambios se actualicen.

Para comprobar qué está enviando entra en la Raspberry Pi y abre un terminal.

Escribe el siguiente comando para suscribirte al topic ​casa/despacho/luz

mosquitto_sub -h localhost -t casa​/despacho/​luz

Cada 10 segundos recibirás un mensaje de un número muy largo.

81
Timestamp son los milisegundos transcurridos desde 1.970 hasta la actualidad, es una
frikada de los informáticos :)

Pero lo importante es que el nodo ​mqtt ​está enviando los datos que recibe desde el nodo
inject​ y más concreto, la propiedad ​payload​.

Ahora te estarás preguntando, ¿cómo puedo enviar un 1 o un 0 para encender o apagar el


LED de NodeMCU?

Sólo tenemos que modificar la propiedad ​payload y ya está. De momento lo vamos a hacer
a través del nodo ​inject​.

Accede a las propiedades del nodo haciendo doble click. En la opción de ​Payload ​haz click
en la lista desplegable.

82
Podemos elegir entre varias opciones para modificar la propiedad ​payload​.

● flow. y global.​: son variables globales a nivel de flujo o de todo Node-RED.


● string​: permite enviar una cadena de texto.
● number​:​ ​permite enviar un número.
● boolean​: envía un booleano.
● JSON​: envía datos en formato JSON.
● buffer​: envía los datos en binario desde un buffer de datos.
● timestamp​: envía la fecha en formato timestamp.

Hasta ahora sólo habíamos visto cómo enviar una cadena de texto seleccionando ​string​.
Ahora vamos a enviar un número.

Selecciona ​number​ y en el campo de texto de Payload pon un 1. Luego haz click en ​Done​.

83
Siempre que hagas un cambio debes hacer click en ​Deploy​ para poder ver los cambios.

Si vas a una terminal de tu Raspberry Pi o miras la que ya tenías abierta donde habías
hecho la suscripción, verás como ahora estarás recibiendo un 1.

84
Debido a la arquitectura que utiliza MQTT, este mensaje será recibido por todos los clientes
que estén suscritos a este topic.

Se ha recibido el mensaje en la Raspberry Pi pero también lo habrá recibido NodeMCU si


está encendido y conectado a la misma red.

Al recibir el número 1, NodeMCU ya tiene la lógica implementada en el ejemplo para


encender el LED. Lo puedes comprobar tu mismo si enciendes NodeMCU.

Para asegurarte de que estás recibiendo el mensaje, puedes abrir el monitor serie. Tiene
que salir algo parecido a lo siguiente.

Además, el LED integrado en la placa NodeMCU tiene que estar encendido.

Ahora vamos a apagar el LED. Sólo tenemos que editar el nodo ​inject y en el Payload poner
un 0.

85
No te olvides de hacer click en ​Done​ y luego ​Deploy​.

Ahora si abres el monitor serie de NodeMCU verás como a los 10 segundos recibes un
mensaje vía MQTT con el ​payload​ a 0 y se apaga el LED de la placa.

Ha sido sencillo ¿verdad?

86
Pero claro, si tenemos que estar editando el nodo cada vez que queremos encender o
apagar el LED, pierde toda posibilidad de automatización.

Imagínate que en vez de encender el LED, tenemos un relé conectado a un pin digital ¿no
crees que sería interesante tener un panel de control para encender y apagar el relé?

Aquí es donde surge la ​magia ​de Node-RED. Vamos a crear nuestro primer panel de control
para controlar el LED con un switch o interruptor.

3.5 Panel de control con Node-RED


Ya hemos visto cómo añadir nuevos nodos a Node-RED. En el ejemplo hemos añadido un
módulo de nodos nuevo que se llama ​dashboard​.

Aquí encontrarás todos los nodos que permiten crear un panel de control. Hay muchos
nodos pero por el momento nos centraremos en 3.

Un nodo para captar información y dos nodos para representar información.

3.5.1 Configurar el dashboard de Node-RED


Vamos a empezar por el principio, configurando el panel de control o dashboard.

Cuando hablo de panel de control, no deja de ser una interfaz de usuario en formato de
página web.

Que sea una página web tiene varias ventajas. La principal es que sólo tenemos que
mantener una interfaz gráfica para que acceder desde un pc, un portátil, un móvil o una
tablet.

Podríamos tener una APP que fuera el panel de control pero ¿te imaginas mantener una
APP para el ordenador, móvil y tablet? Sería un auténtico engorro. Esta es la mayor ventaja
que nos da una página web, una sóla interfaz multiplataforma.

87
Interfaz de usuario web de un panel de control

Una vez que creemos el panel de control se generará una página web que será accesible
dentro de la red donde esté la Raspberry Pi con Node-RED instalado.

Podrás acceder desde un ordenador, un móvil, una tablet o incluso desde una televisión
inteligente.

La interfaz de usuario o página se organiza en pestañas o layouts y grupos. Las pestañas


son páginas diferentes, es como si tuvieras varias pestañas en tu navegador.

Dentro de cada pestaña hay grupos que dividen cada pestaña en secciones para una mejor
organización.

Cada sección a su vez tiene widget que es cómo mostramos u obtenemos los datos. Por
ejemplo, podemos tener un gráfico tipo ​Gauge​, como si fuera un cuentakilómetros, un botón
o interruptor o una gráfica.

88
Vamos a empezar a configurar nuestro primer panel de control. Sigue estos pasos para
hacerlo.

3.5.2 Abrir panel dashboard


Cuando hemos instalado ​node-red-dashboard,​ el módulo de nodos que nos permite crear
un panel de control, aparece un nuevo panel.

89
Si no está el panel ​dashboard​ puedes abrirlo desde el ​Menú>View>dashboard​.

3.5.3 Crear una pestaña o layout del dashboard


Las pestañas o layouts son páginas web diferentes. Imagínate que quieres controlar dos
casas diferentes o un acuario y una planta o diferentes habitaciones.

Podrías tener un layout de la casa habitual y un layout para la casa de vacaciones. O si sólo
tienes una casa podrías tener un layout para cada habitación: salón, cocina, despacho,
habitación 1, etc...

90
Los layout generan páginas diferentes y nos sirven para separar el contenido. En este
ejercicio sólo vamos a tener una.

Dentro del panel ​dashboard hay tres opciones. La primera pone ​Layout​. Cuando entras ves
un texto que pone ​Tabs & Links​.

Esto quiere decir que podemos añadir una pestaña o un enlace al menú de la interfaz web.
Un enlace no es más que un link a una página web.

Vamos a crear un nuevo ​tab​. Pulsa en el botón ​+tab​.

Ahora tenemos un nuevo ​tab o pestaña que tenemos que rellenar con información. Pero
antes vamos a modificarlo un poco haciendo click en ​edit​.

91
Esto abre un panel donde podemos configurar la pestaña. Pon un nombre descriptivo. Por
ejemplo, yo he puesto ​Casa​. Una vez que lo hayas cambiado puedes dar al botón ​Update.

92
Inmediatamente cambia el nombre en la lista de ​Layout​.

3.5.4 Añadir un grupo a la pestaña


Ahora hay que añadir un grupo. Si vuelves a ponerte encima de la pestaña ​Casa que
acabas de crear, aparece un botón que pone ​+group​. Haz click sobre ese botón.

Esto añade un nuevo grupo a la pestaña o layout ​Casa​. En este ejemplo vamos a utilizar
dos grupos, uno para controlar el LED y otro para visualizar la temperatura.

93
Si no visualizas los grupos asegúrate que tienes desplegado el contenido de la pestaña ya
que se puede contraer. La flecha a la izquierda del nombre de la pestaña tiene que estar
hacia abajo.

Si te pones encima del nuevo grupo aparece un botón donde pone ​edit​. Si haces click se
abrirá el panel de configuración del grupo.

Pon un nombre descriptivo, por ejemplo Luz y asegúrate que está seleccionado el ​Tab
Casa.

El resto de parámetros modifican el aspecto visual. Puedes probar diferentes


configuraciones.

Una vez hayas terminado pulsa en botón ​Update​ y se guardarán los cambios.

94
Ahora sólo nos quedaría añadir los widget que son los componentes de la interfaz gráfica
para mostrar y obtener datos.

3.5.5 Añadir un widget


Los widget los encontramos en el módulo de nodos del dashboard, en la parte izquierda del
editor de Node-RED.

Digamos que los widget son los componentes para mostrar información e interactuar con el
usuario.

Hay bastantes widgets. El que nos interesa ahora mismo es el ​switch ​así que lo arrastramos
y lo soltamos dentro del flujo en el área de trabajo.

El triángulo rojo que aparece en el nodo nos está indicando que no está asignado a ningún
grupo de la interfaz gráfica del panel de control.

Si hacemos doble click sobre el nodo se abren las propiedades. Aquí es donde vamos a
asignar este widget al grupo Luz.

También vamos a cambiar la etiqueta (​Label​) que se mostrará en la interfaz gráfica y el


Name ​que es el nombre que quieres que se muestre dentro del nodo en el flujo.

95
Por último no te olvides de pulsar el botón ​Done​.

Con esto ya tenemos la estructura básica de la interfaz web del panel de control. Hemos
creado una pestaña o layout (son las páginas webs), hemos creado un grupo y hemos
añadido un widget al grupo.

La jerarquía sería la siguiente:

- Layout 1
- Grupo 1
- Widget 1
- Widget 2
- Widget 3
- Grupo 2
- Widget 1

96
Ya que lo tenemos, vamos a echar un vistazo de cómo se ve a través de un navegador.
Puedes acceder a la interfaz web de dos formas, accediendo a través de la siguiente url

http:​//IP-RASPBERRYPI:1880/ui/

Donde tienes que sustituir IP-RASPBERRYPI por la IP que tiene asignada la Raspberry Pi,
como hemos visto antes.

También puedes acceder directamente desde Node-RED. Si vas al panel ​dashboard verás
un botón con un cuadrado y una flecha.

Si lo pulsamos se abre una nueva ventana en tu navegador donde puedes ver la pestaña, el
grupo y el interruptor (widget) que hemos creado.

Incluso puedes acceder desde el móvil :)

97
Por último, tenemos que dar la funcionalidad al interruptor. Si lo activas o desactivas
comprobarás que no hace nada.

La idea es que cuando esté ON encienda el LED integrado en NodeMCU y cuando esté en
OFF apague el LED.

Así que vamos a ello, verás que sencillo es con Node-RED.

3.5.6 Conectando el panel de control con MQTT


Lo primero que quiero es que te fijes en el nodo ​switch que hemos añadido al flujo. Han
desaparecido las alertas y aparece el estado en el que está justo debajo del nodo.

Cuando está activo aparece la palabra ​on y un cuadrado verde y cuando está ​off aparece
un cuadro rojo. Eso nos ayudará cuando estemos programando el flujo a saber cuál es su
estado sin entrar en la interfaz web.

El objetivo con el nodo ​switch es que cuando pase de estado ​off a estado ​on envíe un 1 en
el topic ​casa/despacho/luz​.

Para modificar el ​payload que vamos a enviar tenemos que entrar en las opciones del nodo
switch​ así que haz doble click en el nodo.

98
Nos vamos a fijar en la parte de abajo de las opciones, donde pone ​When clicked, send:
que significa ​Cuando hagan click envía:

La configuración por defecto envía ​true cuando el switch pasa a estado ON y ​false cuando
pasa a estado OFF.

Tenemos que modificar esto y hacer que envíe un 1 cuando pase a estado ON y un 0
cuando pase a estado OFF.

Aquí podemos asignar valores cuando el interruptor esté On y cuando esté Off. Se trata de
un valor booleano. O 1 o 0.

Esto lo hacemos cambiando el tipo de dato que enviamos.

99
Si despliegas el selector que hay en el campo ​On Payload​, puedes seleccionar el tipo de
dato que vas a pasar.

Como hemos visto antes, podemos elegir entre unos cuantos. El que necesitamos es un
número así que selecciona ​number​. Como valor pondremos un 1.

En el campo de ​Off Payload​ también haremos lo mismo. Como valor pondremos un 0.

El resultado final sería el siguiente.

No te olvides de pulsar el botón ​Done​ cuando termines.

Vale, por ahora lo que hemos hecho es cambiar el ​Payload del objeto ​msg que se envía
entre los nodos, pero todavía no hemos conectado ningún nodo al ​switch​.

Lo que vamos a hacer a continuación es conectar el nodo ​switch al nodo ​mqtt que teníamos
configurado anteriormente. Ya hemos comprobado que este nodo enviaba un mensaje y
que la placa NodeMCU lo recibía.

Lo que queremos es sustituir el nodo ​inject que enviaba el mensaje cada 10 segundos, se
envíe cada vez que cambiemos el estado del switch.

Cómo el nodo ​inject​ ya no hace falta vamos a eliminarlo.

Para borrar un nodo sólo tienes que seleccionarlo (el borde cambiará de color a naranja) y
luego pulsa la tecla ​supr​ en tu teclado.

Los atajos de teclado como ctrl-z para eliminar la última acción funcionan en el editor de
Node-RED. Puedes añadir, modificar y eliminar atajos de teclado desde desde la opción
Keyboard shortcuts del menú principal de Node-RED.

100
Ahora sólo nos falta conectar el nodo ​switch c​ on el nodo ​mqtt​.

No te olvides de pulsar el botón ​Deploy para que se guarden los datos una vez hayas
terminado.

Lo que hemos hecho con esta simple conexión es muy importante. Hemos conectado la
interfaz web con la placa NodeMCU.

Si vas a la página web del panel de control, podrás encender y apagar el LED de la placa.

Lo más increíble de todo es que hemos montado una interfaz web para comunicar con
NodeMCU sin una línea de código en la parte del servidor ;)

101
¿Notas algo raro en el funcionamiento? Si estás utilizando un ESP8266 te habrás dado
cuenta que el funcionamiento es el contrario al esperado.

Cuando el switch pasa a estado OFF se enciende el LED y cuando pasa a estado ON se
apaga.

Esto es debido a que los pines de la placa donde están conectados los LEDs integrados en
NodeMCU tienen una resistencia pull-up.

Esto hace que su comportamiento sea al contrario, con un estado HIGH en la placa
tenemos 0V y con un estado LOW tenemos 3,3V.

No cambies nada, en los siguientes capítulos volveremos a ver ese código que cargamos
en NodeMCU y lo corregiremos.

Si no conoces NodeMCU a fondo, te recomiendo que mires el ​Curso de Introducción a


NodeMCU​.

Hasta ahora lo que hemos visto es cómo enviar datos de Node-RED a NodeMCU. Lo
siguiente que haremos será enviar datos de NodeMCU a Node-RED.

Podemos enviar cualquier tipo de dato: temperatura, humedad, luminosidad, etc… Todo
esto lo haremos a través de un topic de MQTT.

3.6 Capturando datos con Node-RED


Hemos visto cómo publicar un mensaje en un topic desde Node-RED. Es relativamente
sencillo con el nodo de salida ​mqtt​.

También hemos visto cómo ese mensaje llega hasta NodeMCU si está suscrito al mismo
topic, y dependiendo de la carga útil (​payload​) enciende o apaga un LED.

Ahora toca hacer el camino contrario. Desde NodeMCU se está publicando un dato en el
topic ​casa/despacho/temperatura​.

Lo que vamos a hacer es recoger ese dato y mostrarlo en la interfaz web a través del panel
de control.

3.6.1 Nodo de entrada MQTT


El nodo de entrada ​mqtt se encuentra en el módulo de ​input​. Arrastra el nodo al flujo en el
área de trabajo.

102
Este nodo nos permite recibir mensajes a través de MQTT. Eso sí, antes tenemos que
suscribirnos a un topic.

Para configurar este nodo hacemos como hemos hecho con los demás, doble click sobre el
nodo y se abre el panel de opciones.

Lo primero es comprobar que está seleccionado el broker MQTT que teníamos configurado.
Aquí podemos tener varios broker.

103
En el topic tenemos que poner el nombre del topic al que nos vamos a suscribir
casa/despacho/temperatura​.

Por último pon un nombre descriptivo al nodo. Por ejemplo,​Temperatura​.

El QoS o calidad de servicio lo puedes dejar a 2. No te olvides de pulsar el botón ​Done


cuando termines.

Si ahora damos a ​Deploy estaremos recibiendo los datos que está publicando NodeMCU en
el topic ​casa/despacho/temperatura​.

Node-RED los estará recibiendo pero no lo estamos viendo. Para poder verlo añadimos el
nodo ​debug​ que está en el módulo ​output.​

Este nodo nos ayuda a saber qué está pasando en el flujo. Si lo conectas con el nodo ​mqtt
mostrará la información que se está recibiendo en el topic que hemos configurado.

Si pulsas el botón ​Deploy y tienes tu placa NodeMCU conectada, verás los mensajes que
está enviando al topic ​casa/despacho/temperatura

104
Lo que está sucediendo es que el nodo ​mqtt de entrada que acabamos de configurar recibe
un mensaje de NodeMCU. La carga útil de este mensaje se guarda en la propiedad ​payload
del objeto ​msg​.

Como ya te he comentado, cuando conectamos dos nodos entre sí, la información que se
envían es el propio objeto ​msg​ con todas las propiedades.

Por lo tanto, el nodo ​debug sólo está mostrando la información que le llega en la propiedad
payload​ del objeto ​msg.

Se que es un poco complejo de entender si no tienes experiencia con las clases, pero no te
preocupes ya que todo esto es transparente para nosotros.

Sólo tenemos que quedarnos que en la propiedad ​payload del objeto ​msg está la carga útil
del mensaje MQTT.

Si miras en el panel de la derecha donde pone ​debug, verás que muestra el mensaje que se
está recibiendo de NodeMCU.

Si abres el código que cargamos a la placa NodeMCU, podrás ver el mensaje que se está
enviando.

​if​ (now - lastMsg > ​2000​) {


lastMsg = now;
++value;
​snprintf​ (msg, ​75​, ​"hello world #%ld"​, value);
Serial.print(​"Publish message: "​);

105
Serial.println(msg);
client.publish(​"casa/despacho/temperatura"​, msg);
}

Justo en la línea donde pone ​spintf.​ Envía la cadena “hello world “ concatenada con el valor
de la variable ​value​ que es un contador.

Esto es precisamente lo que se está viendo en el panel ​debug​ de Node-RED.

Pero claro, esta información no es muy útil para nosotros. Lo que vamos a hacer ahora es
enviar datos reales de temperatura obtenidas de un sensor DHT11.

3.6.2 Conectando el sensor DHT11


Vamos a enviar datos reales conectando un sensor de temperatura y humedad a
NodeMCU.

El DHT11 es un sensor muy sencillo de usar y muy útil en nuestros proyectos domésticos.
Pero puede valer cualquier otro sensor que tengamos por casa.

El objetivo es mostrar cómo enviar esos datos a Node-RED para ser representados.

Si quieres ver cómo configurar y usar este sensor te recomiendo que veas estu ​tutorial paso
a paso del DHT11​.

106
3.6.2.1 Circuito eléctrico

Es un circuito muy sencillo. Conectamos el DHT11 al pin 3V3 y GND de NodeMCU. El pin
de datos lo conectamos al pin D4 por ejemplo.

Da lo mismo el pin que utilices siempre y cuando lo tengas en cuenta en el código.

La resistencia pull-down puede ser de 5 kΩ o 10 kΩ.

107
También existe el sensor DHT11 que viene montado en una PCB o circuito integrado. En
este caso no necesitarás la resistencia pull-down y sólo tienes que conectar el pin de datos
a la entrada digital.

Una vez que hemos conectado el sensor a la placa NodeMCU, sólo nos queda programar el
código para que todo funcione correctamente.

3.6.2.2 Integración con el código de MQTT


Ahora viene quizás la parte más abstracta y complicada. Tenemos que juntar el código que
teníamos del ejemplo con MQTT y NodeMCU con el código para leer el sensor DHT11.

Vamos a ver todo el código paso a paso.

3.6.2.2.1 Importar librerías

// Librerías
#include ​<ESP8266WiFi.h>
#include ​<PubSubClient.h>
#include ​<DHT.h>

108
Importamos las librerías ​ESP8266WiFi.h para conectar el módulo a la red WiFi, la librería
PubSubClient.h para integración de un cliente MQTT y la librería ​DHT.h para poder leer el
sensor de temperatura y humedad DHT11.

3.6.2.2.2 Declaración de variables

// Información para conexión a la red WiFi


const​ ​char​* ssid = ​"NOMBRE-RED-WIFI"​;
const​ ​char​* password = ​"CONTRASEÑA-RED-WIFI"​;

Estas dos variables sirven para almacenar el nombre de la red WiFi y la contraseña.
Sustituye los textos por los datos de tu red WiFi.

Debe ser la misma red a la que está conectada Raspberry Pi.

// Datos MQTT
const​ ​char​* mqtt_server = ​"IP-RASPBERRYPI"​;
const​ ​char​* mqtt_topic_luz = ​"casa/despacho/luz"​;
const​ ​char​* mqtt_topic_temp = ​"casa/despacho/temperatura"​;

Los datos básicos del protocolo MQTT son:

● mqtt_server: IP del Broker MQTT es decir, la IP fija asignada a la Raspberry Pi.


Sustituye IP-RASPERRYPI por tu IP.
● mqtt_topic_luz: topic donde nos suscribimos para el control de la luz.
● mqtt_topic_temp: topic para publicar los datos de temperatura.

// Configuración DHT11
const​ byte dhtPin = D4;
const​ byte dhtTipo = DHT11;
DHT ​dht​(dhtPin, dhtTipo);

El DHT11 necesita dos datos de configuración. El pin donde envía los datos, ​dhtPin y el tipo
de sensor, ​dhtTipo​. En el pin ponemos el ​D4​ y en el tipo ​DHT11​.

Este último parámetro sólo vale si estás utilizando un DHT11, si se trata de un DHT22
tendrás que poner ​DHT22​.

// Conexión a la red WiFi y al Broker


WiFiClient espClient;
PubSubClient ​clientMqtt​(espClient);

109
Creamos una instancia a la clase ​WiFiClient llamada ​espClient que nos permitirá abrir una
conexión por TCP/IP. Luego creamos una instancia a la clase ​PubSubClient ​a la que
llamamos ​clientMqtt​.

En el constructor de esta última clase pasamos el objeto ​espClient​.

// Tiempos para enviar los mensajes


long​ lastMsg = ​0​;
const​ ​int​ tiempoEnvioMsg = ​2000​;

Las dos últimas variables nos ayudarán a gestionar cada cuánto se publican los mensajes
en el topic.

La variable ​lastMsg almacena el tiempo transcurrido desde la última publicación. La variable


tiempoEnvioMsg dice cada cuánto tiempo se publica un nuevo mensaje. El tiempo está en
milisegundos.

Asignamos un valor inicial a la variable ​tiempoEnvioMsg de 2.000 milisegundos es decir, 2


segundos.

Esto hará que, automáticamente, cada dos segundos se envíe la temperatura a Node-RED.

3.6.2.2.3 Función setup

void​ ​setup​() {
​// Iniciamos comunicación serie
Serial.begin(​115200​);

​// Modo del pin LED


pinMode(BUILTIN_LED, OUTPUT);

​// Conexión con la red Wifi


setup_wifi();

​// Configuración MQTT


clientMqtt.setServer(mqtt_server, ​1883​);
clientMqtt.setCallback(callback);
}

En la función ​setup() ​sólo vamos a programar cosas que se ejecutan una vez.

Comenzamos iniciando la comunicación serie con una velocidad de 115200 con


Serial.begin()​. Esto nos servirá para poder mostrar mensajes en el monitor serie.

110
Luego ponemos el pin integrado en la placa en modo salida. Eso lo hacemos con la función
pinMode() a la que pasamos como argumentos el número del pin (​BUILTIN_LED es una
constante del sistema que representa el pin donde está conectado el LED) y el modo
OUTPUT​.

Para conectarnos a la red WiFi llamamos a la función ​setup_wifi()​. Esta función la veremos
un poco más adelante.

Lo siguiente es configurar la conexión al broker MQTT. Esto lo hacemos llamando a la


función ​clientMqtt.setServer()​.

Cómo parámetros pasamos la IP del broker y el puerto. Por defecto, el protocolo MQTT
siempre utiliza 1883 para conexiones sin SSL.

Por último, asignamos la función ​callback que se ejecutará cuando reciba un mensaje en el
topic o los topic a los que NodeMCU esté suscrito.

Esto lo hacemos con la llamada a la función ​clientMqtt.setCallback() y como parámetro la


función ​callback​ que se ejcutará.

El nombre de esta función puede ser cualquiera. En este caso coincide su nombre con lo
que representa pero la podríamos haber llamado, ​funcionRecibirMensaje​ por ejemplo.

Luego veremos más en detalle esta función ya que es muy importante.

3.6.2.2.4 Función setup_wifi

void​ ​setup_wifi​() {

delay(​10​);
​// Iniciamos la conexión con la red WiFi
Serial.println();
Serial.print(​"Conectando a "​);
Serial.println(ssid);

​// Intentamos conectar


WiFi.begin(ssid, password);

​while​ (WiFi.status() != WL_CONNECTED) {


delay(​500​);
Serial.print(​"."​);
}

111
Serial.println(​""​);
Serial.println(​"WiFi conectada"​);
Serial.println(​"IP: "​);
Serial.println(WiFi.localIP());
}

En la función ​setup_wifi()​ se realiza la conexión con la red WiFi.

Lo primero es hacer un retardo de 10 ms con la función ​delay​. Esto se hace para que de
tiempo al chip WiFi del ESP8266 a responder.

Luego mostramos unos mensajes por el monitor serie para indicar que estamos conectando
con la red.

Hacemos la conexión con la función ​WiFi.begin() a la que pasamos como argumentos el


nombre de la red WiFi, ​ssid​, y la contraseña, ​password​.

El bucle que viene a continuación se repetirá hasta que se produzca la conexión.

Una vez conectados mostramos un mensaje por el monitor serie indicando que la conexión
se ha realizado con éxito y se muestra la IP asignada a la placa.

Este es el procedimiento típico que tenemos que hacer en cualquier programa para
conectarnos a una red WiFi con un ESP8266.

3.6.2.2.5 Función callback

void​ ​callback​(​char​* topic, byte* payload, ​unsigned​ ​int​ length) {


Serial.print(​"Mensaje recibido["​);
Serial.print(topic);
Serial.print(​"] "​);
​// Mostramos el mensaje en el monitor serie
​for​ (​int​ i = ​0​; i < length; i++) {
Serial.print((​char​)payload[i]);
}
Serial.println();

​// Si el topic coincide con el de la luz apagamos o encendemos


​if​ (​strcmp​(topic, mqtt_topic_luz) == ​0​) {
​// Si el parámetro recibido es un 1 apagamos el LED
​// Esto es debido a que los LEDs integrados en la placa
​// funcionan de forma invertida en NodeMCU.
​if​ ((​char​)payload[​0​] == ​'1'​) {

112
​// Encendemos el LED
digitalWrite(BUILTIN_LED, LOW);
​// En caso contrario
} ​else​ {
​// Apagamos el LED
digitalWrite(BUILTIN_LED, HIGH);
}
}
}

La función ​callback es la que se ejecuta cuando se recibe un mensaje en el topic o los topic
a los que estemos suscritos.

Funciona como una ​interrupción en Arduino​. Cuando ejecutamos el programa dentro del
microcontrolador el proceso normal es el siguiente:

1. Incluye las librerías.


2. Crea las variables.
3. Ejecuta la función ​setup()
4. Ejecuta una y otra vez en bucle la función ​loop()

Por lo tanto, una vez que hemos pasado los 3 primeros pasos se queda en la función ​loop()
ejecutando una y otra vez hasta el infinito y más allá.

Entonces ¿cuando ejecuta la función ​callback​?

Cuando en la función ​setup() hemos configurado la función ​callback con


clientMqtt.setCallback()​, lo que estamos haciendo es decir al microcontrolador: “​Oye, que
me voy a suscribir a un topic y cuando tengas una notificación del broker quiero que
ejecutes esta función (la que pasamos por parámetro)​”.

Por lo tanto, aunque nosotros no lo veamos, el microcontrolador está esperando que el


broker le de un aviso si recibe un mensaje en algún topic al que esté suscrito.

En ese preciso instante, cuando se recibe el aviso, para la ejecución del bucle ​loop(), esté
donde esté, y ejecuta la función ​callback.​

Cuando termina de ejecutar la función ​callback sigue por donde se quedó en la función
loop()​. Es el mismo principio de funcionamiento que las interrupciones.

Por este motivo es importante hacer que la función ​callback se ejecute lo más rápido
posible.

113
Estamos interrumpiendo la ejecución normal del programa y por eso se recomienda no
utilizar ningún ​delay​ ni ningún proceso que tarde mucho dentro de esta función.

Por defecto, la función callback, admite 3 parámetros:

● topic​: es un array de caracteres que contiene el topic donde se ha recibido el


mensaje.
● payload​: es un array de bytes donde se encuentra la carga útil del mensaje.
● length​: es la longitud del array de la carga útil.

La primera parte de la función lo único que hace es mostrar el ​topic y el ​payload en el


monitor serie.

Fíjate bien en el bucle. Utiliza el parámetro ​length para recorrer el array de bytes ​payload
que es donde está la carga útil.

​// Mostramos el mensaje en el monitor serie


​for​ (​int​ i = ​0​; i < length; i++) {
​Serial​.​print​((​char​)payload[i]);
}

Para convertir un byte en un carácter utilizamos el modificador ​(char)​. Ha esto se le llama


cast​ y sirve para convertir un tipo de dato en otro.

Todo lo anterior nos sirve para mostrar información sobre el mensaje y el topic. Ahora lo que
tenemos que hacer es la lógica para hacer una cosa u otra dependiendo del mensaje
recibido.

Lo primero es comprobar en qué topic se ha recibido el mensaje. Podemos estar suscritos a


varios topic y cada vez que recibamos un mensaje comprobaremos el topic desde el que se
ha recibido y haremos una cosa u otra dependiendo de la carga útil.

Imagínate que estás suscrito a dos topic y cada uno ejecuta una acción diferente. De aquí la
sentencia condicional ​if​ para filtrar los topic.

​// Si el topic coincide con el de la luz apagamos o encendemos


​if​ (strcmp(topic, mqtt_topic_luz) == 0
​ ​) {

En esta sentencia condicional comprobamos si el ​topic recibido es el mismo al que nos


hemos suscrito y que está almacenado en la variable ​mqtt_topic_luz​.

Esta variable contiene el topic ​casa/despacho/luz​.

114
Pero cómo hemos visto, la variable ​topic es un array de caracteres (​char*​) al igual que la
variable ​mqtt_topic_luz​.

Para comparar dos arrays de caracteres tenemos que usar la ​función ​strcmp​.

Esta función compara uno por uno los elementos de cada array. Si son exactamente iguales
devuelve 0 y en caso contrario devuelve otro valor.

Por lo tanto, si coinciden los topic ejecutará el código que hay dentro de la sentencia ​if​. Aquí
es donde implementaremos la lógica para encender o apagar un LED.

​// Si el parámetro recibido es un 1 apagamos el LED


​// Esto es debido a que los LEDs integrados en la placa
​// funcionan de forma invertida en NodeMCU.
​if​ ((​char​)payload[​0​] == ​'1'​) {
​// Encendemos el LED
​digitalWrite​(BUILTIN_LED, ​LOW​);
​// En caso contrario
} ​else​ {
​// Apagamos el LED
​digitalWrite​(BUILTIN_LED, ​HIGH​);
}

El primer ​if, una vez hemos comprobado que se trata del mismo topic, comprueba si el
primer elemento del array de bytes es un 1.

Volvemos a hacer un ​cast (cambio de tipo de dato) para convertirlo en un carácter. Sólo
comprobamos el primer elemento (​payload[0]​) ya que si recuerdas, sólo vamos a enviar un
1 y un 0.

Si la carga útil fuera más de un carácter tendríamos que utilizar la función ​strcmp que
hemos visto antes.

Cuando se recibe 1 encendemos el LED con la función ​digitalWrite(BUILTIN_LED, LOW) y


cuando se recibe 0 apagamos el LED con la función ​digitalWrite(BUILTIN_LED, HIGH)​.

Ahora te estarás preguntando “​pero Luis, lo has puesto al revés, LOW es para estado bajo
(0V) y HIGH para estado alto (5V)​”. Efectivamente esto es así.

Pero recuerda lo que nos ha sucedido cuando configuramos el nodo ​switch en Node-RED.
Funciona al revés debido a que este pin tiene una resistencia pull-up.

Con esto solucionamos ese problema y ahora funcionará de forma lógica.

115
Por último tengo que hacer una aclaración, si estuviéramos suscritos a más de un topic, la
función ​callback sería la encargada de gestionar todos los mensajes. Da lo mismo el topic al
que pertenezca el mensaje.

Esto tiene que quedar claro.

Como ha sido una explicación bastante larga vamos a dar un repaso rápido de todo lo que
hemos visto.

La función ​callback se ejecutará siempre que se reciba un mensaje en alguno de los topic a
los que esté suscrita la placa NodeMCU.

Recibe 3 parámetros. El ​topic​, el ​payload​ (carga útil) y ​length​ (longitud) de la carga útil.

Lo primero que tenemos que hacer es saber el topic al que pertenece el mensaje.

Una vez sabemos desde dónde se envía, comprobamos la carga útil y ejecutamos una cosa
u otra dependiendo de esa carga útil.

A continuación vamos a ver la lógica que se implementa en la función ​loop()​.

3.6.2.2.6 Función loop

void​ ​loop​() {

​// Comprobación si hemos perdido conexión


​if​ (!clientMqtt.connected()) {
reconnect();
}

​// Procesamos los mensajes entrantes


clientMqtt.loop();

​// Si ha pasado el tiempo marcado enviamos la temperatura


​if​ (millis() - lastMsg > tiempoEnvioMsg) {
lastMsg = millis();

​char​ msg[​50​];
​snprintf​ (msg, ​50​, ​"%2.1f"​, dht.readTemperature());
Serial.print(​"Publicando mensaje: "​);
Serial.println(msg);
clientMqtt.publish(mqtt_topic_temp, msg);
}

116
}

La función ​loop es la que se ejecutará una y otra vez hasta que se reciba un mensaje y pare
la ejecución para ir a la función ​callback​ como hemos visto antes.

El primer ​if que nos encontramos comprueba si hemos perdido conexión con el broker
MQTT. Esto lo hacemos con la función ​clientMqtt.connected()​.

Esta función devuelve ​true si hay conexión y ​false si se ha desconectado. En este último
caso ejecuta el código dentro del ​if donde llamamos a la función ​reconnect() que veremos
más adelante.

Con la función ​clientMqtt.loop() comprobamos si hay mensajes nuevos. En caso de haberlos


se ejecutará la función ​callback​ que hayamos configurado.

La siguiente parte del código es un temporizador es decir, nos va a permitir ejecutar un


código cada cierto intervalo de tiempo.

Estarás pensando ¿por qué no utilizamos un ​delay​? Por norma general, no es


recomendable utilizar la función ​delay en ningún caso, salvo cuando el tiempo de espera
sea muy pequeño.

Por ejemplo el ​delay de 10 ms que he utilizado para esperar a que el chip WiFi esté
operativo.

Imagínate que utilizamos aquí un ​delay de 10 segundos. Esto bloquearía la ejecución (la
pararía por completo) y no permitiría comprobar si hay conexión con el broker MQTT o si se
han recibido mensajes nuevos.

Para hacer esto utilizamos una técnica muy común. Básicamente consiste en comprobar en
cada iteración del bucle cuánto tiempo ha pasado desde que se ejecutó la última vez el
código que queremos ejecutar cada cierto intervalo de tiempo.

En el caso de que haya pasado el tiempo marcado, ejecutamos el código y volvemos a


empezar.

Analicemos el código que viene a continuación.

​// Si ha pasado el tiempo marcado enviamos la temperatura


​if​ (​millis​() - lastMsg > tiempoEnvioMsg) {
lastMsg = ​millis​();

​char​ msg[​50​];

117
snprintf (msg, ​50​, ​"%2.1f"​, dht.​readTemperature​());
​Serial​.​print​(​"Publicando mensaje: "​);
​Serial​.​println​(msg);
clientMqtt.publish(mqtt_topic_temp, msg);
}

En la sentencia ​if hago una resta. Utilizo la función ​millis() para obtener los milisegundos
que han transcurrido desde que se inició el programa.

A este tiempo le resto la variable ​lastMsg que, como hemos visto en la declaración de
variables, vale 0.

Por lo tanto, si han transcurrido 1.000 ms (1 segundo) desde la ejecución del programa y le
resto cero, el resultado es 1.000.

La condición es que siempre que esta resta sea mayor que la variable ​tiempoEnvioMsg
ejecutará el código dentro del ​if​. Esta variable la he inicializado a 2.000 ms (2 segundos).

Por lo tanto, sólo se ejecutará cuando pasen 2.000 ms.

Una vez dentro de la sentencia condicional, lo primero es guardar el valor actual de ​millis()
en la variable ​lastMsg​.

Esto nos permite resetear el tiempo a cero ya que si en ese mismo instante se hace la resta,
como las dos variables valen igual el resultado sería cero.

Ahora según vaya pasando el tiempo se irá aproximando a los 2.000 ms para volver a
ejecutar el código.

Creo que entiendes lo que quiero decir ¿no? Bien, pues continuemos con el código.

Después de asignar el valor a la variable ​lastMsg​, creo un array de caracteres de 50


elementos. Este array será la carga útil del mensaje MQTT.

En la siguiente sentencia utilizo la función ​snprintf()​. Esta función es como el ​Serial.print() o


Serial.println()​. La diferencia es que en vez de mostrar los datos por pantalla, almacena los
datos en un array de caracteres.

Por lo tanto, lo que estamos haciendo es imprimir en una variable caracteres.

La sintaxis sería la siguiente:

snprintf(array, longitud, formato, valor);

118
Donde cada parámetro significa:

● array: es el array de caracteres donde vamos a guardar el valor. Es el resultado de


esta función.
● longitud: la longitud máxima que tendrá la cadena que genere la función. Es un
número entero.
● formato: es una cadena que indica el formato. Esta parte es importante ya que nos
permite decir, por ejemplo, cuantos números decimales queremos utilizar. Puedes
ver los diferentes formatos en ​esta web​.
● valor: es el valor que queremos transformar a cadena.

Si quieres saber más sobre esta función te recomiendo que mires ​esta web​.

snprintf (msg, ​50​, ​"%2.1f"​, dht.​readTemperature​());

Analizando más en detalle nuestro caso concreto, puedes ver cómo el primer parámetro de
la función ​snprintf es el array de caracteres que había declarado antes, ​msg​. Más adelante
utilizaremos este array como carga útil del mensaje.

La longitud máxima es de 50 y el formato es ​%2.1f​. El ​% se pone para indicar que a partir


de ahí irá un valor. En este ejemplo sólo vamos a convertir un único valor a cadena pero
podríamos tener varios.

El formato ​2.1f quiere decir que vamos a convertir un tipo de dato ​float que tendrá 2
números enteros y 1 decimal. Si por ejemplo queremos 3 decimales tendría que poner ​2.3f
o si quisiera tener 3 números enteros y 2 decimales sería ​3.1f​.

Mucho ojo con esto, si pones 2 enteros y el valor que vas a convertir en cadena tiene 3
enteros, uno se perderá.

Por último añado como parámetro el valor que quiero convertir. Recuerda que lo que
queremos enviar a Node-RED es la temperatura del DHT11.

Para obtenerla sólo tenemos que llamar a la función ​dht.readTemperature()​. Esta función
nos devuelve un valor de coma flotante o decimal.

Ahora entenderás el formato que he elegido ​2.1f​, 2 enteros y un decimal. La temperatura,


salvo que quieras medir qué calor hace dentro de un horno, no llegará a las centenas :)

El resultado de esta parte sería el array ​msg con la temperatura del DHT11. Si tenemos una
temperatura de 22,3452º C, el resultado será un array como el siguiente:

2 2 . 4

119
Creo que vas entendiendo cómo lo hace el código.

Por último, dentro de la sentencia ​if​, muestro el mensaje por el monitor serie y envió el
mensaje MQTT.

​Serial​.​print​(​"Publicando mensaje: "​);


​Serial​.​println​(msg);
clientMqtt.publish(mqtt_topic_temp, msg);

Para enviar el mensaje utilizo la función ​clientMqtt.publish()​. Esta función toma dos
parámetros.

El primer parámetro es el topic donde se publica el mensaje y está almacenado en la


variable ​mqtt_topic_temp​. Su valor es el que hemos visto antes ​casa/despacho/temperatura​.

El segundo parámetro es la carga útil que la tenemos almacenada en la variable ​msg​.

Y con esto ya habríamos enviado un mensaje. Recuerda que este mensaje se enviará cada
tantos milisegundos configurados en la variable ​tiempoEnvioMsg​.

Si queremos enviar cada 5.000 ms (5 segundos) sólo tenemos que cambiar el valor en la
declaración de la variable.

Por último vamos a ver qué hace la función ​reconnect()​.

3.6.2.2.7 Función reconnect

void​ ​reconnect​() {
​// Repetimos hasta que se conecte con el Broker MQTT
​while​ (!clientMqtt.connected()) {
Serial.print(​"Esperando conexión con MQTT..."​);
​// Intentamos conectar
​// El parámetro es el nombre que tiene este cliente
​if​ (clientMqtt.connect(​"NodeMCUClient"​)) {
Serial.println(​"Conectdo"​);
​// Nos suscribimos al topic de la luz
clientMqtt.subscribe(mqtt_topic_luz);
} ​else​ {
Serial.print(​"Fallo al conectar, rc="​);
Serial.print(clientMqtt.state());
Serial.println(​" Intentando conectar en 5 segundos"​);
​// Esperamos 5 segundos

120
delay(​5000​);
}
}
}

Esta función es la encargada de conectarse con el broker MQTT y suscribirse a los topic.

Como hemos visto en la función ​loop() si en algún momento se pierde la conexión, llamará a
esta función y la restablecerá.

La primera vez que ejecutemos el programa, al no tener conexión con el broker MQTT
ejecutará esta la función ​reconnect()​.

La función comienza con un bucle w ​ hile.​ La condición de este bucle viene determinada por
la función ​clientMqtt.connected() que, como hemos visto antes, devuelve ​true si hay
conexión y ​false​ en caso contrario.

Por lo tanto, el bucle ​while​ se repetirá mientras no haya conexión con el broker MQTT.

Una vez dentro mostramos un mensaje para informar con la función ​Serial.println() y ejecuta
una condicional ​if-else​.

La primera condición viene definida por la función ​clientMqtt.connect()​. Esta función hace un
intento de conexión con el broker MQTT.

Si consigue conectar con el broker, pasa por el ​if​, en caso contrario se va al ​else​.

Ahora seguramente te estés preguntando ¿cómo sabe cuál es la IP del servidor donde está
el broker MQTT?

Si recuerdas la función ​setup() hemos llamado a la función ​clientMqtt.setServer(mqtt_server,


1883)​. Los parámetros que hemos pasado son la IP del broker y el puerto.

Estos parámetros se almacenan dentro de la clase y cuando llamamos a la función


clientMqtt.connect() la clase ya tiene la IP y el puerto. Era sólo aclarar esto por si no te
habías dado cuenta.
Una vez que ha conseguido conectar ya podemos suscribirnos a los topic que queramos.
Eso lo hacemos con la función ​clientMqtt.subscribe(“NOMBRE-TOPIC”).​

​// Nos suscribimos al topic de la luz


clientMqtt.subscribe(mqtt_topic_luz);

121
Como ves es muy sencillo eso sí, cada vez que perdemos conexión tenemos que
suscribirnos ya que no se queda almacenado en ningún sitio.

En el caso de que no consiga conectar irá por el ​else​, donde muestro un mensaje de error y
hago una espera con la función ​delay​ de 5.000 ms (5 segundos).

Y ahora que hemos visto todo el código ya podemos pasar a Node-RED pero antes te dejo
el código completo para que puedas descargarlo y cargarlo a tu placa.

3.6.2.3 Código completo


Recuerda que tienes que sustituir los datos de la WiFi, ​ssid ​y ​password​. También tienes que
poner la IP asignada a tu Raspberry Pi en tu red WiFi.

DESCARGAR EL CÓDIGO COMPLETO

Una vez cargado abre el monitor serie. Acuérdate de cambiar la velocidad de transmisión
para que coincida con la que hemos configurado en el código, 115200.

Deberás tener algo parecido a esto.

122
Sólo nos queda mostrar los datos en la interfaz web del panel de control en Node-RED,
vamos a ello.

3.7 Mostrando los datos en la interfaz web


Ya tenemos todo preparado para ver los datos de temperatura en el panel de control de
Node-RED.

Lo primero es comprobar que están llegando bien. Con la configuración que tenemos en
Node-RED, podemos ir a la pestaña ​debug​ y comprobar la temperatura.

Como puedes comprobar los datos están llegando correctamente. Ahora vamos a
mostrarlos en la interfaz web.

3.7.1 Añadiendo un nodo gauge


El nodo ​gauge ​funciona como un cuentakilómetros. Es una semicircunferencia con una
flecha que indica un valor.

Añádelo al flujo y conéctalo con el nodo ​mqtt​ de temperatura.

123
De un nodo pueden salir varias conexiones. La documentación oficial dice que en teoría no
hay un límite.

En este caso estamos enviando los datos al nodo ​debug y al nodo ​gauge​. El nodo ​debug
hará que los datos de temperatura que llegan por MQTT se vean en el panel debug.

El nodo ​gauge hará que los datos se vean en la interfaz web del panel de control de
Node-RED.

Ahora vamos a modificar las propiedades del nodo ​gauge​. Hacemos como siempre, doble
click sobre el nodo y abrimos el panel de opciones.

124
Lo primero es seleccionar el grupo dentro del panel, en la propiedad ​Group​. Seleccionamos
Luz ​que pertenece a la pestaña o layout ​Casa​.

La etiqueta es lo que se mostrará en la interfaz web. Pon algo descriptivo como


Temperatura en la propiedad ​Label​.

La propiedad ​Units indica las unidades del valor que estamos representando. El DHT11 está
enviando los datos en grados Celsius (ºC).

En la propiedad ​Range establecemos el valor máximo y mínimo del rango. Por ejemplo
entre 0 y 40.

También puedes cambiar el color que se muestre dependiendo de la temperatura en la


propiedad ​Colour gradient​.

125
Por último ponemos un nombre al nodo para identificarlo dentro del flujo. No te olvides de
dar al botón ​Done​ para guardar los cambios. Ahora sólo queda pulsar el botón ​Deploy​.

Si abres la interfaz web verás los cambios. ¡¡¡ Ya estamos mostrando la temperatura !!!

Fíjate bien que tenemos un grupo que es ​Luz ​y en ese grupo estamos mostrando el ​switch ​y
el ​gauge ​de temperatura.

Para que quede mejor, vamos a separar cada ​widget​ en un grupo diferente.

3.7.2 Añadiendo un nuevo grupo


Ya hemos visto cómo añadir un nuevo grupo así que voy a ir rápido.

Abre el panel ​dashboard y encima del ​tab ​Casa pulsa el botón ​+group​. Esto añadirá un
nuevo grupo al ​tab​.

126
Ahora vamos a modificarlo pulsando el botón ​edit​ del ​Group 2​ que hemos creado.

Sólo modificamos el nombre y pulsamos el botón ​Update​.

Por último, vamos a cambiar el grupo al que pertenece el nodo ​guage que está mostrando
la temperatura.

Entra en las opciones del nodo ​gauge​ que se llama Temperatura Gauge.

Sólo vamos a modificar la propiedad ​Group para seleccionar el grupo Temperatura. Vuelve
a pulsar al botón ​Done​ y a ​Deploy​.

Ahora si abres la interfaz web del panel de control verás los cambios.

127
¿A qué queda mucho mejor :) ?

3.7.3 Añadiendo un gráfico de histórico


Ahora vamos a añadir un gráfico de histórico para ir monitoreando la temperatura. En el
módulo de nodos del ​dashboard​ selecciona el nodo c​ hart​.

Conéctalo con el nodo ​input​ ​mqtt​.

Ahora tenemos 3 nodos conectados al nodo ​mqtt es decir, estamos viendo los datos en tres
sitios diferentes: el panel ​debug​, en el ​gauge de la interfaz web y ahora en el histórico con el
nodo ​chart​.

128
Vamos a cambiar las opciones del nodo ​chart​. Haz doble click sobre el nodo.

En la opción ​Group​ seleccionamos el grupo ​Temperatura ​del tab o pestaña ​Casa​.

En la opción ​Label​ ponemos un texto descriptivo. Por ejemplo Histórico.

En la opción ​X-axis ponemos durante cuánto tiempo mostramos los datos. Por ejemplo, si
ponemos 2 horas nos mostrará el histórico de las últimas 2 horas.

Ojo, con este nodo no estamos almacenando los datos en ningún sitio. Sólo guarda los
datos durante ese periodo de tiempo y luego los elimina.

129
Para hacer un histórico real y que se guarden los datos, tendríamos que utilizar una base de
datos como SQLite. Esto lo dejo para otro tutorial :)

En la opción ​X-axis Label ponemos el formato de la hora. Yo he elegido ​HH:mm que


mostrará la hora con dos dígitos (HH) y los minutos con otros dos dígitos (mm).

En la opción ​Y-axis ponemos el mínimo y el máximo de la temperatura. Por ejemplo de 0ºC


a 40ºC.

Por último ponemos un nombre descriptivo al nodo. Ahora sólo queda pulsar en ​Done ​y
Deploy​.

Abre la interfaz web y comprobarás los cambios realizados.

Mucho mejor :)

3.7.4 Cambiando el aspecto del panel de control


Por último vamos a cambiar el aspecto del panel de control. Esto lo hacemos accediendo al
panel ​dashboard​ y luego a la pestaña ​Theme​.

130
En la opción ​Style tenemos un menú desplegable donde podemos seleccionar entre tres
estilos:

● Light (default): es el que estamos utilizando ahora mismo.


● Dark: es igual con tonos oscuros.
● Custom: permite modificar los colores de la interfaz web.

Selecciona ​Dark y pulsa ​Deploy.​ Si abres la interfaz web verás como ha cambiado el
aspecto.

Y con esto tenemos montado nuestro primer proyecto con MQTT, NodeMCU y Node-RED.

131
Ahora vamos a seguir avanzando y veremos un nuevo componente que puede resultar muy
útil, el relé WiFi Sonoff basado en el ESP8266.

132
4 Relé Wifi Sonoff y Node-RED
Una vez que hemos visto cómo podemos empezar a trabajar con Node-RED, MQTT y
NodeMCU vamos a hacer algo práctico para el hogar o nuestro trabajo.

Cuando queremos controlar una luz o un aparato eléctrico que funciona a 220V, utilizamos
un componente que se llama relé.

Un relé es un dispositivo electromagnético que funciona como un interruptor. Por medio de


una bobina y un electroimán podemos accionar uno o varios contactos para controlar
circuitos eléctricos independientes.

Esto lo hacemos a través de un circuito eléctrico de 5V o 3V3. Básicamente lo que hacemos


es hacer circular una corriente por una bobina que induce un campo magnético y acciona
una parte mecánica para cerrar o abrir el circuito.

Para nosotros, a partir de ahora, será como un interruptor.

Debemos de llevar mucho cuidado al trabajar con estos componentes ya que nos
permiten controlar corrientes altas y pueden causarnos grandes daños.

Para instalar un relé en nuestra casa podemos hacerlo de diferentes maneras. Podemos
comprar un módulo relé, conectarlo a nuestra placa y a funcionar. Es relativamente sencillo
hacer esto.

133
Sin embargo, podemos comprar un dispositivo que tiene un relé y toda la electrónica
necesaria para empezar a trabajar. Si además te digo que ese dispositivo tiene incorporado
un ESP8266 ¿cómo te quedas?

La idea de este capítulo es ​hackear un Sonoff de Itead y poderlo programar desde el IDE de
Arduino para controlarlo desde la Raspberry Pi con Node-RED y MQTT.

No te asustes, va a ser muy sencillo :)

La empresa china ​Itead fabrica dispositivos para la automatización del hogar basados en el
ESP8266. Muchos de ellos se pueden hackear con un poco de ingeniería inversa y con la
ayuda de Google :)

En este capítulo nos centraremos en el relé WiFi Sonoff Basic.

4.1 Sonoff WiFi Basic


Como ya te he comentado, se trata de un dispositivo que tiene incorporado un relé, un
ESP8266 y toda la electrónica necesaria para que funcione desde el primer momento.

Hay diferentes modelos en el mercado. Que funcionan por GSM, por radiofrecuencia y el
que veremos aquí, que se controla por WiFi.

Su nombre comercial es Sonoff WiFi Basic.

134
Lo puedes comprar por unos ​9,5€ en Amazon​. En Aliexpress puedes comprarlo por ​4,5€
aunque como ya sabrás, tarda entre 2 y 4 semanas en llegar a tu casa.

Cuando lo recibes, ya viene precargado un firmware (programa) para que funcione con la
plataforma en la nube de Itead, la empresa que lo fabrica.

Sin embargo, su uso es muy limitado y aburrido :) Tú, como buen Maker, querrás cargar tu
propio programa y que haga lo que tu quieres.

Vamos a verlo por dentro. Puedes abrirlo sin ningún miedo eso sí, no lo conectes a la red
eléctrica por ahora.

Para abrirlo sólo tienes que quitar los tornillos de las tapas que cubren los cables y con un
destornillador separar la carcasa.

135
Sencillo ¿no? Pues veamos que nos encontramos dentro.

4.1.1 Circuito eléctrico Sonoff


Una vez que hemos quitado la tapa vamos a ver qué hay dentro del dispositivo. Voy a hacer
un pequeño resumen de la electrónica.

136
La parte que nos interesa es la parte de comunicación con el ESP8266 que viene integrado.
Luego veremos cómo podemos acceder a esta parte.

Este sería el esquema general de la electrónica de este componente que se divide en 7


partes.

Las que nos interesan ahora mismo a nosotros son:


● Entrada AC​: por donde conectamos el dispositivo a la red eléctrica.
● Salida AC Max 10A​: por donde conectamos el aparato eléctrico que queremos
controlar. Admite un máximo de 10A de consumo que equivalen a 2,2 kW si la red
eléctrica es de 220V.
● Pulsador​: lo podemos utilizar para cambiar de modos o para configurar el dispositivo.
● LED​: puede ser útil para saber qué está haciendo y en qué modo o estado está.
● Pines y comunicación serie​: esta parte nos permite cargar el programa al
microcontrolador e incluso conectar más componentes a la placa.

Las otras partes del circuito te las muestro para que sepas qué es. Se recomienda no tocar
nada de esta parte del circuito:
● Relé 5V​: es el propio relé que trabaja con 5V.
● Conversor AC-DC​: este componente convierte la corriente alterna (AC) en corriente
continua (DC). Nos permite alimentar los componentes como el ESP8266 o el relé.

Si damos la vuelta al circuito eléctrico nos encontramos lo siguiente:

137
Aquí podemos ver el ESP8266 y la antena WiFi. Es importante conocer dónde están estos
componentes aunque no vamos a tocarlos.

Pero para poder programar un Sonoff con nuestro propio programa, hay que conocer dónde
están las entradas/salidas de propósito general o GPIO (del inglés ​General Purpose
Input/Output​). También conocidos como pines.

Esto es lo que vamos a ver a continuación.

4.1.2 Acceso a los pines


La idea es poder localizar los pines que nos permita cargar un programa nuevo al
microcontrolador. Vamos a necesitar localizar los pines de alimentación (3V3), tierra (GND),
RX y TX (para la comunicación serie) y los pines para controlar el pulsador, el LED y el relé.

Existen varias maneras de trabajar con este componente. Una ya te la he dicho, a través de
la plataforma en la nube de Itead.

Otra opción es utilizar un firmware (programa) muy completo. Se llama ​ESPurna y está
desarrollado por ​Xosé Perez​. No sólo sirve para el relé WiFi Sonoff, también tiene
compatibilidad con otros dispositivos que llevan integrados un ESP8266.

ESPurna tiene muchas posibilidades y muchas posibles configuraciones. El mayor


inconveniente que encuentro es que necesitas algo de experiencia para configurar o instalar
este firmware.

138
Mi recomendación es empezar aprendiendo cómo funciona un Sonoff con MQTT y
Node-RED y luego pasar a algo más completo como es ESPurna.

En su web encontramos mucha documentación y entre esa documentación encontramos


dónde están los pines que nos interesan.

● GPIO14​: es un pin digital para poder conectar otros componentes. Por ejemplo
podríamos conectar un sensor de temperatura, humedad o cualquier otro
componente digital.
● GND​: es el pin de tierra.
● TX​: es el pin de transmisión de datos del puerto serie.
● RX​: es el pin de recepción de datos del puerto serie.
● 3V3​: es el pin para alimentar el ESP8266. El voltaje máximo es de 3,3V y lo
utilizaremos para alimentar el ESP8266 mientras programamos o lo probamos.
● GPIO12​: en este pin está conectado el relé. A través del código conseguiremos
apagar y encender el relé.
● GPIO0​: aquí está conectado el pulsador. Ya veremos más adelante lo útil que
resulta este pulsador para programar el microcontrolador.
● GPIO13​: es el pin donde está conectado el LED.

Básicamente lo que tenemos que hacer es programar el ESP8266 como si fuera un ​módulo
ESP-01​.

Este módulo fue el primero que vio la luz y el que inició el ascenso meteórico del ESP8266.
Pero carece de un sistema adaptador para convertir señales de USB a Serie y viceversa.

139
Placas como Arduino UNO, MEGA, MKR1000, NodeMCU, Wemos, etc… ya traen este
adaptador y sólo nos preocupamos de conectar el puerto USB y programar.

En este caso todo es un poco más complejo. Tenemos que conectar, de alguna manera,
ese adaptador para poder cargar nuestro programa.

4.1.3 Adaptador TTL USB a Serie


Existen muchos modelos y marcas de adaptadores USB a Serie también conocidos como
TTL o FTDI.

Todos funcionan de la misma forma. Tienen dos pines para la comunicación RX y TX y los
pines de alimentación. La gran mayoría proporcionan los 5V o 3,3V que vamos a necesitar
para alimentar nuestros microcontroladores.

Asegurate de esto último. Muchos de los microcontroladores trabajan con 3,3V entre ellos el
ESP8266.

Si lo compras en Amazon puedes encontrar ​desde los 3€​. Si te vas a Aliexpress lo puedes
encontrar ​por 2€​.

Este es el que tengo yo. Lo típico es que el mismo componente pueda suministrar o 3,3 V o
5V. En este caso tenemos un jumper para seleccionar un voltaje u otro.

Lo importante son los pines. De todos los que tenemos a nuestra disposición utilizaremos el
RX y TX para enviar la información en serie, el 3V3 y el GND para alimentar el ESP8266.

Por lo tanto, tenemos que conectar los pines del FTDI al Sonoff de la siguiente manera.

140
Fíjate bien que cruzamos los cables de RX y TX. El resto 3V3 con 3V3 y GND con GND.

Ahora viene la duda ¿cómo hacemos la conexión si en el Sonoff no hay pines? No queda
otra que soldar si lo queremos hacer bien.

Para cargar un programa sin ningún peligro, debemos asegurarnos que todo está bien
conectado.

Antes de nada tengo que decirte que yo soy un auténtico negado para soldar y he
conseguido soldar estos pines así que si yo he podido, tu también puedes :)

4.1.4 Soldando los pines en el Sonoff


Para esta parte vamos a necesitar el siguiente material:
● Soldador de 30W. Tienes un kit muy interesante por ​unos 18€ para empezar aunque
te recomiendo que si vas a hacer la compra, interesa comprar uno de buena calidad
por un poco más.
● Estaño de buena calidad. Es recomendable una proporción de 60% estaño y 40%
plomo. No escatimes en el estaño o te arrepentirás en un futuro. Por un poco menos
de ​8€​ tienes 100 g.
● Pines hembra. Estos pines nos ayudarán a conectar los cables semirígidos dupont
de una forma muy sencilla. Por ​1,5€​ puedes comprar montón de cables.

Si tienes dudas te recomiendo que leas ​este artículo donde te explican cómo tienes que
hacerlo.

A mi me ayudó mucho esta imagen de referencia de ​Adafruit​.

141
La idea es que al final tengamos los pines hembra soldados a la placa electrónica de
Sonoff.

142
Sólo vamos a utilizar cuatro, los que ya he comentado: 3V3, RX, TX y GND. Los puedes
conectar según el esquema que hemos visto antes.

143
Por fin estamos listos para cargar nuestro primer programa en un Sonoff hackeado, que
ilusión :)

No alimentar con más de 3,3 V la placa ya que se puede dañar.

4.1.5 Configuración del IDE de Arduino


Antes de subir el código a la placa tenemos que configurar el IDE de Arduino. Xose
comenta en la WiKi de ESPurna que tendríamos que modificar el IDE de Arduino.

Esto se hace para que nos muestre una opción concreta, pero con las últimas versiones del
IDE (a partir de la 1.8) ya no hace falta hacer nada.

Si has podido programar NodeMCU, podrás programar el relé Sonoff.

Selecciona el tipo de placa Generic ESP8266 Module en la opción del menú


Herramientas>Placa>Generic ESP8266 Module

144
Respecto a la configuración que tienes que elegir sólo te puedo hablar de la configuración
que a mi me funciona. Es la que tiene por defecto cuando seleccionas esta placa.

145
Lo único que he cambiado es la velocidad de subida (​Upload Speed​). Yo tengo
seleccionada la máxima, 921600 baudios.

Si ves que con esta velocidad te da algún error, prueba a bajar la velocidad hasta conseguir
que funcione.

4.1.6 Hola mundo con el relé Sonoff


Nuestro primer programa es muy básico y nos servirá para comprobar que tenemos acceso
al pulsador y al LED.

Vamos a ver el código. Comenzamos con la declaración de las variables

// Declaración de variables pines


const​ ​byte​ pinLed = ​13​;
const​ ​byte​ pinPulsador = ​0​;

// Estado LED
boolean​ estadoLed = true;

Necesitamos 3 variables, ​pinLed ​que almacena el pin donde está conectado el LED,
pinPulsador ​que almacena el pin donde está conectado el pulsador y una variable para
guardar el estado en el que se encuentra el LED, ​estadoLed​ (​true​ es igual a ​HIGH ​y ​false ​es
igual a ​LOW​).

Ahora vamos con la función ​setup()​.

void​ ​setup​() {
​// Modo de los pines
​pinMode​(pinLed, ​OUTPUT​);
​pinMode​(pinPulsador, ​INPUT​);
}

Lo único que hacemos es poner el pin del led, ​pinLed​, en modo ​OUTPUT​ y el pin del
pulsador en modo ​INPUT​.

La función ​loop()​ quedaría de la siguiente manera.

void​ ​loop​() {
​// Comprobamos que esté apretado el pulsador
​if​ (!​digitalRead​(pinPulsador)) {
​// Cambiamos el estado

146
estadoLed = !estadoLed;
​delay​(​500​);
}

​digitalWrite​(pinLed, estadoLed);
}

Básicamente lo que hago es comprobar si se ha pulsado el pulsador. Si te das cuenta,


compruebo si el estado está en ​LOW o ​false​. Esto es debido a que este pulsador está
conectado con una ​resistencia pull-up​.

Esto implica que en estado de reposo, sin pulsar, tengamos a la entrada de ese pin un
estado ​HIGH y cuando se pulsa tengamos un estado ​LOW​. Es lo mismo que nos ha
sucedido con la placa NodeMCU.

Dentro del ​if​, si está pulsado cambiamos el estado y esperamos 500 ms para que no
detecte varias pulsaciones seguidas.

Por último cambiamos el estado del pin del LED con ​digitalWrite​.

Bueno, ha sido sencillo ¿no? Ahora vamos a cargar este código al ESP8266.

DESCARGAR EL CÓDIGO COMPLETO

4.1.7 Subiendo el código al ESP8266


No voy a entrar muy en detalle de cómo funciona un microcontrolador a la hora de cargar un
programa en la memoria.

Básicamente lo que tenemos son dos posibles estados: modo UART o modo Flash.

El modo UART nos permite cargar el programa en la memoria del ESP8266. Para entrar en
este modo tenemos que tener el pin GPIO0 en estado ​LOW (0V) y el pin GPIO2 en estado
HIGH​.

Del pin GPIO2 no debemos preocuparnos. Al igual que hemos visto en el ejemplo anterior
con el pin GPIO0 del pulsador, este pin tiene una resistencia pull-up interna que hace que
en estado de reposo esté en estado ​HIGH.

Sin embargo, el GPIO0 también está siempre en este estado y por lo tanto, debemos poner
el pin en estado LOW. Esto lo conseguimos pulsando el pulsador antes de conectar el
adaptador USB a Serie o FTDI al ordenador.

147
Por otro lado tenemos el modo Flash que es el modo de ejecución normal. Por defecto está
activado este modo así que cuando tu conectas el FTDI al ordenador, el microcontrolador
ejecuta el código que tenga cargado en ese momento.

Este modo también se activa de forma automática una vez has cargado un nuevo programa
al microcontrolador.

Resumiendo, los pasos a seguir para cargar un programa son estos:

1. Conecta todos los cables entre el FTDI y la placa.


2. Asegúrate de elegir la placa y el puerto correctos en el IDE de Arduino.
3. Aprieta el pulsador que está en el relés Sonoff.
4. Sin dejar de pulsar, conecta el FTDI al puerto USB del ordenador.
5. Carga el programa.

Cuando cargues el nuevo programa, estarás eliminando el programa que venía


precargado de fábrica. Esto implica que ya no podrás utilizar la plataforma en la nube de
Itead.

148
149
En ocasiones, a veces bastante a menudo, te saldrá un error como este.

Es bastante común, más de lo que debería. Básicamente lo que nos está diciendo es que
no ha podido subir el programa a la placa.

¿Cómo se resuelve? Repitiendo el mismo proceso que he explicado antes para cargar el
programa.

Pulsamos el pulsador, sin dejar de pulsar conectamos el FTDI al puerto USB del ordenador
y cargamos el programa.

No te desesperes ya que en muchas ocasiones he tenido que hacer el proceso más de 5


veces hasta que he conseguido cargar el programa al ESP8266.

Si finalmente no te termina de funcionar, prueba a bajar la velocidad de subida.

Cuando la carga del programa se hace con éxito obtenemos un mensaje como este.

Una vez que ha terminado de cargar se pone en modo Flash de forma automática y ejecuta
el programa.

150
El estado inicial es con el LED apagado.

Si ahora aprietas el pulsador verás como se enciende el LED.

Con esto acabamos de cargar nuestro primer programa a un relé Sonoff y por lo tanto, lo
hemos hackeado ;)

¿Imaginas qué es lo que vamos a hacer ahora? Efectivamente, vamos a comunicarlo con
Node-RED vía MQTT y así lo podremos controlar desde nuestra aplicación.

151
4.2 Relé WiFi Sonoff y Node-RED
En esta parte de la guía vamos tener que hacer varias cosas a nivel de software y de
hardware para controlar el relé WiFi Sonoff desde Node-RED.

Lo primero será programar y cargar el código necesario para que el relé Sonoff se conecte a
Node-RED con el protocolo MQTT.

Luego veremos cómo conectar el relé a la red eléctrica para poder controlarlo con
Node-RED.

Gracias a todo esto seremos capaces de automatizar, prácticamente, cualquier cosa. Así
que vamos a ello y empecemos por el código que se carga dentro del relé Sonoff.

4.2.1 Programando el relé Sonoff


Ya hemos visto que el mismo código que utilizamos para NodeMCU o para Arduino vale
para el relé Sonoff.

Un buen punto de partida puede ser el código que hemos cargado a NodeMCU. En este
código veíamos cómo suscribirse a un topic y cómo enviar mensajes.

El topic para recibir mensajes (suscripción) será ​casa/despacho/rele​. Y el topic para publicar
mensajes será ​casa/despacho/estadorele​.

Como verás a lo largo de este tutorial, vamos a necesitar publicar mensajes para mantener
sincronizados el estado del relé con la interfaz web.

Pero antes, quiero mostrarte una librería muy interesante que nos facilitará la vida. Se llama
WiFiManager y nos permite configurar la red WiFi sin modificar nada de código.

Lo hace creando un punto de acceso o AP (del inglés ​Access Point​). La primera vez que
arranque el ESP8266 si no tiene una conexión WiFi configurada, podrás acceder al
ESP8266 para configurarla.

Veamos cómo se hace a través de este ejemplo.

4.2.1.1 Instalando librería WiFiManager


Podemos ​instalar una librería en el IDE de Arduino de diferentes maneras. Una de ellas es a
través del gestor de librerías que se encuentra en la opción del menú ​Programa>Incluir
Librerías>Gestionar Librerías​.

152
Una vez que se abre el gestor, debemos buscar la librería ​WiFiManager ​e instalar la librería.

Además necesitarás instalar las librerías ​DNSServer ​y ​ESP8266WebServer​. Las puedes


buscar en el Gestor de Librerías y hacer el mismo proceso.

153
Para probar cómo funciona WiFiManager lo mejor es abrir el ejemplo que se encuentra en
Archivo>Ejemplos>WiFiManager>AutoConnect​.

154
Es el más sencillo que hay, servirá de base para nuestro programa. Antes de cargar el
código, abre el monitor serie así podrás ver que está sucediendo.

Sigue los pasos para cargar un programa al ESP8266:

1. Apretando el pulsador conecta el FTDI al USB


2. Luego suelta el pulsador
3. Ya puedes cargar el código a la ESP8266
4. Recuerda que esto puede dar error, no te desesperes :)

Si ha ido todo bien, ya podemos configurar la red WiFi desde nuestro móvil. Da lo mismo el
sistema operativo o la marca, en todos funcionan igual.

155
En el monitor serie te tiene que aparecer algo parecido a esto.

Intenta estar cerca del relé Sonoff para configurar la WiFi. Accede al listado de las redes
WiFi de tu dispositivo.

Deberías ver una red donde pone ​AutoConnectAP​. Esta WiFi no necesita contraseña.

156
Una vez que hayas accedido a la red WiFi se abrirá una página web donde tendrás tres
opciones: ​Configure WiFi, Configure WiFi (No Scan), Info y Reset​.

Aunque te sorprenda, esta página web está dentro del propio ESP8266. Ahora mismo está
funcionando como si fuera un servidor web.

Selecciona la primera opción donde pone ​Configure Wifi​. En la siguiente pantalla selecciona
la red WiFi de tu casa. Por ejemplo la mía es ​vodafone03F8​.

157
Esto te muestra un formulario donde te pide una contraseña. La escribes y pulsas el botón
save​.

158
Si todo ha ido bien, en el móvil se tiene que haber cerrado la pantalla donde has puesto la
contraseña de la WiFi.

Además, habrá desaparecido el punto de acceso ​AutoConnectAP​.

Ahora es importante mirar el monitor serie donde tienes que tener algún mensaje parecido a
este.

Lo que ha sucedido aquí es que hemos guardado los datos de la WiFi en la memoria del
ESP8266. Ahora si desconectas el relé Sonoff y lo vuelves a conectar, se conectará sólo a
la red.

Lo sorprendente es cuando te lo llevas a otro lugar y lo intentas conectar a otra red WiFi. La
librería WiFiManager detectará que no está la red que habíamos configurado anteriormente
e iniciará de nuevo el proceso que acabamos de ver.

159
Podrás acceder al punto de acceso y configurar una nueva red WiFi sin necesidad de cargar
un nuevo programa, increíble ¿verdad?

Una vez que tenemos configurada la WiFi, vamos a pasar a conectar el relé Sonoff al broker
MQTT.

4.2.1.2 Conectando con MQTT


Ya hemos visto cómo conectar un ESP8266 con MQTT a Node-RED. Con el relé Sonoff es
prácticamente lo mismo.

Pero en este caso, vamos a tener en cuenta el LED y el pulsador. El LED lo utilizaremos
para que nos diga si está encendido o apagado y el pulsador para poder encender y apagar
de forma manual.

Es un código muy parecido al que vimos con NodeMCU al que además vamos a añadir
WiFiManager.

Lo veremos parte por parte así quedará todo más claro.

4.2.1.3 Importación de librerías

// Librerías
#include ​<ESP8266WiFi.h>
#include ​<PubSubClient.h>

// Librerías WiFiManager
#include ​<DNSServer.h>
#include ​<ESP8266WebServer.h>
#include ​<WiFiManager.h>

Importamos las librerías ​ESP8266WiFi.h y ​PubSubClient.h para conectarnos con el


protocolo MQTT a la red WiFi.

También importamos las librerías ​DNSServer.h, ESP8266WebServer.h y ​WiFiManager.h


para poder utilizar WiFiManager.

4.2.1.4 Declaración de variables

// Datos MQTT
const​ ​char​* mqtt_server = ​"IP-RASPBERRYPI"​;
const​ ​char​* mqtt_topic_rele = ​"casa/despacho/rele"​;
const​ ​char​* mqtt_topic_estado_rele = ​"casa/despacho/estadorele"​;

// Conexión a la red WiFi y al Broker

160
WiFiClient​ espClient;
PubSubClient clientMqtt(espClient);

// Pin del relé y del LED


const​ ​byte​ pinRele = ​12​;
const​ ​byte​ pinLed = ​13​;

// Interrupcion
const​ ​byte​ pulsador = ​0​;
boolean​ estadoRele = false;
volatile​ ​boolean​ enviarEstado = false;

Comenzamos declarando tres arrays del tipo char para la configurar la comunicación con el
broker MQTT.

La variable ​mqtt_server almacena la IP del broker MQTT (es la misma IP con la que hemos
configurado la Raspberry Pi).

La variable mqtt_topic_rele ​almacena el topic ​casa/despacho/rele donde vamos a recibir


datos para controlar el relé desde Node-RED.

La variable ​matt_topic_estado_rele almacena el topic donde vamos a enviar mensajes


sobre el estado del relé. Este topic informará de las acciones manuales para encender y
apagar el relé desde el pulsador.

Es importante que el estado del relé esté actualizado tanto en Sonoff como en Node-RED.
Luego veremos cómo se hace.

Acuérdate de cambiar IP-RASPBERRYPI por la IP estática de la Raspberry Pi.

Aunque la configuración de la red WiFi la hagamos con el WiFiManager, vamos a necesitar


declarar una instancia de la clase ​WiFiClient para utilizarla en la clase ​PubSubClient y así
poder conectar con el broker MQTT.

Lo siguiente que hago es declarar dos variables, ​pinRele y ​pinLed​, para almacenar los pines
donde está conectado el relé y el LED. Esto son el 12 (GPIO12) y el 13 (GPIO13).

Por último declaro 3 variables para almacenar el pin del pulsador (GPIO0) en una variable
del tipo ​byte llamada ​pulsador​, el estado del relé en una variable del tipo ​boolean que se
llama ​estadoRele​ y una tercera variable del tipo ​boolean​ que se llama ​enviarEstado​.

161
Esta última variable tiene el modificador ​volatile​. Cuando utilizamos esta directiva del
compilador estamos diciendo que la variable guarde su valor en la memoria RAM y no en el
registro de almacenamiento.

Esto servirá, como veremos más adelante, para modificar su valor dentro de una función
ISR de una interrupción​. Gestionaremos el pulsador a través de una interrupción.

La variable ​enviarEstado nos va a permitir saber si tenemos o no tenemos que enviar el


estado a Node-RED.

En este programa no vamos a utilizar ninguna variable para almacenar la información de la


red WiFi (ssid y contraseña). Todo esto se gestiona desde la librería WiFiManager como ya
hemos visto.

4.2.1.5 Función setup

void​ ​setup​() {
​// Iniciamos comunicación serie
​Serial​.​begin​(​115200​);

​// Modo del pin LED y del relé


​pinMode​(pinRele, ​OUTPUT​);
​pinMode​(pinLed, ​OUTPUT​);
​pinMode​(pulsador, ​INPUT​);

​// Apagamos los dos pines


​digitalWrite​(pinRele, ​LOW​);
​digitalWrite​(pinLed, ​HIGH​);

​// Iniciamos WiFiManager


WiFiManager wifiManager;

​// Configuración del punto de acceso


wifiManager.autoConnect(​"releSonoffAP"​);

​// Configuración MQTT


clientMqtt.setServer(mqtt_server, ​1883​);
clientMqtt.setCallback(callback);

​// Configuración de interrupción


​attachInterrupt​(digitalPinToInterrupt(pulsador), enviarEstadoMQTT,
FALLING);
}

162
En la función ​setup​ comienzo configurando el monitor serie. Lo siguiente es modificar el
modo de los pines del relé y del LED a ​OUTPUT​ y el pin del pulsador a ​INPUT​.

También hay que cambiar los estados iniciales del relé y del LED. Para el relé ponemos
estado ​LOW​ (apagado) y para el LED estado ​HIGH (apagado​).

Recuerda que el pin del LED está configurado con una resistencia ​pull-up​. Para encender
necesitamos un estado ​LOW​ y para apagar un estado ​HIGH​.

Luego iniciamos la librería WiFiManager declarando una instancia de la clase ​WiFiManager


a la que llamo ​wifiManager y a continuación configuro el punto de acceso o AP llamando a
la función ​wifiManager.autoConnect()​.

Esta función admite un parámetro, el nombre del punto de acceso, ​releSonoffAP​, pero
puedes poner el nombre que quieras. Este parámetro sirve para localizar el relé Sonoff
entre las redes WiFi disponibles.

Lo siguiente que hago es configurar el protocolo MQTT con la función ​clientMqtt.setServer()


a la que pasamos como parámetros la IP del broker y el puerto.

También hay que configurar la función ​callback ​con la llamada a la función


clientMqtt.setCallBack() y como parámetro el nombre de la función que vamos a utilizar
como callback.

Por último nos queda ​configurar la interrupción​. Utilizaremos esta técnica para detectar
cuando se pulsa el pulsador.

Llamamos a la función ​attachInterrupt(digitalPinToInterrupt(pulsador), enviarEstadoMQTT,


FALLING)​ que admite 3 parámetros:

● digitalPinToInterrupt(pulsador)​: el primer parámetro indica el pin del microcontrolador


que vamos a utilizar como interrupción. Tenemos que enviar el ordinal, por eso
utilizo la función ​digitalPinToInterrupt ​para que devuelva el ordinal del pin del
pulsador.
● enviarEstadoMQTT​: es la función ISR que se ejecutará cada vez que se produzca
una interrupción. Su funcionamiento es parecido a la función ​callback,​ pero no es lo
mismo que quede claro.
● FALLING​: este parámetro indica cuando se detectará la interrupción. ​FALLING
quiere decir que se ejecutará cuando cambie de estado de ​HIGH​ a ​LOW​.

Y con esto damos por finalizada la función ​setup()​.

163
4.2.1.6 Función callback

void​ callback(​char​* topic, ​byte​* payload, ​unsigned​ ​int​ length) {


​Serial​.​print​(​"Mensaje recibido["​);
​Serial​.​print​(topic);
​Serial​.​print​(​"] "​);
​// Mostramos el mensaje en el monitor serie
​for​ (​int​ i = ​0​; i < length; i++) {
​Serial​.​print​((​char​)payload[i]);
}
​Serial​.​println​();

​// Si el topic coincide con el de la luz apagamos o encendemos


​if​ (strcmp(topic, mqtt_topic_rele) == ​0​) {
​// Si el parámetro recibido es un 1 apagamos el LED
​// Esto es debido a que los LEDs integrados en la placa
​// funcionan de forma invertida en NodeMCU.
​if​ ((​char​)payload[​0​] == ​'1'​) {
​// Encendemos el LED
​digitalWrite​(pinLed, ​LOW​);
​// Activamos el relé
​digitalWrite​(pinRele, ​HIGH​);
​// Cambiamos estado del relé
estadoRele = true;
​// En caso contrario
} ​else​ {
​// Apagamos el LED
​digitalWrite​(pinLed, ​HIGH​);
​// Desactivamos el relé
​digitalWrite​(pinRele, ​LOW​);
​// Cambiamos estado del relé
estadoRele = false;
}
}
}

La función ​callback hace lo mismo que en el código de NodeMCU. Siempre que se reciba
un mensaje en el topic donde esté suscrito, se ejecutará.

La primera parte muestra el mensaje que se ha recibido por el monitor serie, para debugar.
Luego filtramos por el topic, sólo nos interesan, de momento, los mensajes que lleguen a
casa/despacho/rele​ que está almacenado en la variable ​mqtt_topic_rele​.

164
Siempre que se reciba un 1 en la carga útil del mensaje, encenderá el LED y encenderá el
relé. En el caso de que la carga útil sea un 0, se apagan estos dos componentes.

Es una lógica muy sencilla, lo único que tienes que tener en cuenta es que el LED está
configurado con una resistencia ​pull-up​. Por lo tanto, si cambias a estado ​LOW estarás
encendiendo el LED y con un estado ​HIGH​ estarás apagando el LED.

Por último, guardamos el estado en el que se encuentra el relé en la variable ​estadoRele​.


Cómo ya te he comentado, tenemos que tener claro en qué estado se encuentra tanto en el
hardware como en Node-RED.

Cuando configuremos la parte de Node-RED, todo esto tomará sentido.

4.2.1.7 Función loop

void​ ​loop​() {

​// Comprobación si hemos perdido conexión


​if​ (!clientMqtt.​connected​()) {
reconnect();
}

​// Procesamos los mensajes entrantes


clientMqtt.​loop​();

​// Si tenemos que enviar el estado a Node-RED lo enviamos


​if​ (enviarEstado) {
​// Cambiamos para que no vuelva a enviar
enviarEstado = false;

​// Cambiamos estado del relé


estadoRele = !estadoRele;

​// Encendemos o apagamos el relé y LED


​digitalWrite​(pinLed, !estadoRele);
​digitalWrite​(pinRele, estadoRele);

​// Enviamos el mensaje


​char​ msg[​1​] = {​'1'​};

​// Si ha sido apagado actualizamos el mensaje


​if​ (!estadoRele) {
msg[​0​] = ​'0'​;
}

165
​// Mostramos información por el monitor serie
​Serial​.​print​(​"Publicando mensaje: "​);
​Serial​.​println​(msg);

​// Publicación del mensaje


clientMqtt.publish(mqtt_topic_estado_rele, msg);
}
}

En la función ​loop comenzamos comprobando si hay conexión con el broker MQTT, de no


haberla llama a la función ​reconnect()​.

Luego procesamos los mensajes con la función ​clientMqtt.loop()​.

La siguiente parte comprueba si hay que enviar el mensaje o no evaluando en la sentencia


if​ el valor de la variable ​enviarEstado​.

Esta variable cambiará su estado cada vez que se pulse el pulsador del relé Sonoff, sólo en
ese caso se enviará un mensaje al topic ​casa/despacho/estadorele que será leído, como
veremos más adelante, por Node-RED.

Todo esto lo hacemos dentro de la condicional ​if​ siempre que haya que enviar el estado.

Lo primero dentro de la condicional es poner la variable ​enviarEstado a ​false para que no


vuelva a enviar el mensaje hasta que no se vuelva a pulsar.

Luego cambiamos el estado del relé almacenado en la variable ya que al pulsar, estamos
encendiendo o apagando el relé. Este estado se almacena en la variable ​estadoRele​.

Las siguientes dos sentencias encienden/apagan el LED y el relé. Al poner ​!estadoRele lo


que hacemos es obtener el resultado inverso por ejemplo, si es f​ alse devolverá ​true y
viceversa.

Eso se hace en el LED debido a que, como ya te he dicho, el LED funciona al revés por la
resistencia ​pull-up​.

Sin embargo el relé funciona de forma correcta y no hay que hacer nada.

La última parte es enviar el mensaje como en el código que hemos cargado en NodeMCU.
La única diferencia es que directamente vamos a enviar o un 1 o un 0 dependiendo del
estado en el que se encuentre el relé.

166
No hay que hacer ningún tipo de transformación.

Para enviar el mensaje al topic utilizamos la función ​clientMqtt.publish() donde pasamos por
parámetros el topic, ​mqtt_topic_estado_rele​, y el mensaje almacenado en el array ​msg​.

Con esto terminamos la función ​loop()​.

4.2.1.8 Función reconnect

void​ reconnect() {
​// Repetimos hasta que se conecte con el Broker MQTT
​while​ (!clientMqtt.​connected​()) {
​Serial​.​print​(​"Esperando conexión con MQTT..."​);
​// Intentamos conectar
​// El parámetro es el nombre que tiene este cliente
​if​ (clientMqtt.​connect​(​"releClient"​)) {
​Serial​.​println​(​"Conectado"​);
​// Nos suscribimos al topic de la luz
clientMqtt.subscribe(mqtt_topic_rele);
} ​else​ {
​Serial​.​print​(​"Fallo al conectar, rc="​);
​Serial​.​print​(clientMqtt.state());
​Serial​.​println​(​" Intentando conectar en 5 segundos"​);
​// Esperamos 5 segundos
​delay​(​5000​);
}
}
}

La función ​reconnect ​es exactamente igual salvo que esta vez nos vamos a suscribir al topic
casa/despacho/rele​ que está almacenado en la variable ​mqtt_topic_rele​.

Por lo demás funciona de la misma manera, mientras que no se conecte no saldrá del bucle
while​ y una vez que se conecte, se suscribe al topic ​casa/despacho/rele​.

4.2.1.9 Función enviarEstadoMQTT

void​ enviarEstadoMQTT() {
enviarEstado = true;
}

La última función es muy simple. Es la función ISR que se ejecutará cuando se pulse el
pulsador.

167
Una vez que se pulse, cambiará a ​true la variable ​enviarEstado​. Como hemos visto en la
función ​loop()​, cuando ​enviarEstado es ​true entra dentro del ​if y envía el mensaje al topic
casa/despacho/estadorele​.

Se que es un código un poco largo y seguramente algunas partes no las llegues a entender
todavía. Te aconsejo que lo repases un par de veces para aclarar dudas.

Para ver que todo funciona correctamente, vamos a hacer las primeras pruebas desde el
cliente MQTT en Raspberry Pi.

DESCARGAR EL CÓDIGO COMPLETO

4.2.1.10 Probando el código


Vamos a probar el código en el relé Sonoff. Hacemos los mismos pasos que hemos visto
hasta ahora.

1. Apretando el pulsador conecta el FTDI al USB


2. Luego suelta el pulsador
3. Ya puedes cargar el código a la ESP8266
4. Recuerda que esto puede dar error, no te desesperes :)

Una vez que cargue el programa, vamos a abrir una terminal en la Raspberry Pi para
mandar un mensaje al topic del relé.

Escribe el siguiente comando

mosquitto_pub -h IP-RASPBERRY -t casa/despacho/rele -m "1"

Sustituye ​IP-RASPBERRY por la IP de tu Raspberry Pi. Esto publicará un mensaje con un


payload de ​“1”​ en el topic ​casa/despacho/rele​.

168
Si te fijas en el relé Sonoff, se habrá encendido el LED integrado dentro del circuito. Ya
estamos controlando el dispositivo por el protocolo MQTT.

169
Prueba a apagar el LED enviando un mensaje con un payload de ​“0”​.

mosquitto_pub -h IP-RASPBERRY -t casa/despacho/rele -m "0"

Estamos controlando el LED pero ¿qué pasa con el relé? El relé no está funcionando
porque no está alimentado.

Se alimenta de la red eléctrica y por eso no funciona. Para probar el relé tenemos que
conectar Sonoff a la red eléctrica. Esto lo haremos un poco más adelante.

Lo siguiente que haremos será comprobar que el relé Sonoff está publicando mensajes
cuando se pulsa el pulsador.

Abre un nuevo terminal o en el mismo que tenías abierto y escribe el siguiente comando.
mosquitto_sub -h IP-RASPBERRY -t casa/despacho/estadorele

Esto hará que la terminal se quede esperando a recibir un mensaje. Si pulsamos el pulsador
del relé Sonoff, tendrá que aparecer un 1 o un 0, dependiendo del estado en el que esté.

Ya hemos comunicado el relé Sonoff con la Raspberry Pi, ha sido un camino largo pero por
fin lo hemos conseguido.

170
Ahora vamos a conectar el relé Sonoff a la red eléctrica y comprobar que podemos
encender y apagar una lámpara por ejemplo.

4.2.2 Conectando el relé Sonoff a la red eléctrica


Lo primero que vamos a hacer es poner la carcasa a la placa electrónica. No tiene mayor
misterio.

No pongas las tapas laterales de momento, tenemos que conectar los cables.

Mucho ojo, ahora vamos a trabajar con una corriente alta y puede ser peligroso. Toma
todas las precauciones posibles, lo primero es tu seguridad. Para conectar los cables al
relé Sonoff no los conectes a la red eléctrica.

171
El relé WiFi Sonoff se puede utilizar para muchas cosas, para controlar una luz, una bomba
de agua, un motor o lo que sea. Yo he preparado dos cables con dos enchufes, uno macho
y otro hembra.

En la carcasa del relé Sonoff viene indicado cual es la entrada (​Input)​ y cual es la salida
(​Output​).

172
Además indica con una N (del inglés ​Neutral o Nothing Line​) el Neutro o la tierra (GND) y
con una L (del inglés ​Line​) el vivo tanto en la entrada como en la salida.

En la corriente alterna se utilizan dos cables, uno referenciado a tierra que tendrá 0V y otro
a un voltaje referenciado desde tierra.

En principio no tiene que preocuparnos mucho ya que funcionará tanto si invertimos la


polaridad como si no.

Siempre que se pueda, conectaremos el vivo con el vivo y el neutro con el neutro. Cuando
utilizamos un cable como el que te estoy utilizando yo, es complicado ir con el multímetro
para averiguar cual es el vivo y cual es el neutro.

Si lo vas a dejar fijo, si que interesa averiguar cuál es el neutro y el vivo y dejarlo bien
conectado.

La conexión con los cables es muy sencilla, sólo tenemos que desatornillar los tornillos e
introducir cada cable en su agujero.

173
Por último pon las tapas en su lugar y pones los tornillos. Deja todo bien cubierto para que
no sufras ningún percance.

174
Bueno, pues ya tenemos todo listo para empezar a controlar el relé Sonoff Wifi desde
Node-RED.

Antes podemos utilizar el cliente MQTT de la Raspberry Pi para comprobar que todo
funciona bien.

Prueba a conectar una lámpara a un extremo del cable y el otro a un enchufe. Envía el
siguiente comando desde la terminal de Raspberry Pi para encender la lámpara.

mosquitto_pub -h IP-RASPBERRY -t casa/despacho/rele -m "1"

También puedes apagar enviando el siguiente comando.

mosquitto_pub -h IP-RASPBERRY -t casa/despacho/rele -m "0"

175
Es increíble ¿verdad? Todo trabajo tiene su recompensa y la nuestra ha sido crear un
dispositivo domótico desde cero :)

Ahora sólo nos queda integrarlo todo dentro de un flujo de Node-RED. Es la parte más
sencilla quizás así que adelante.

4.2.3 Controlando el relé Sonoff con Node-RED


Vamos a comenzar con Node-RED así que abre un navegador y ves a la siguiente url.

http://192.168.0.167:1880

Sustituye la IP por la de tu Raspberry Pi. Ahora puedes hacer dos cosas, crear un flujo de
trabajo nuevo o eliminar todos los nodos que tenías del ejercicio anterior para comenzar uno
nuevo.

Yo voy a eliminar todos los nodos y comenzar de cero. Para empezar vamos a ver las
propiedades del flujo haciendo doble click en la pestaña que pone Flow 1.

176
Esta acción abre un nuevo panel donde podemos hacer varias cosas con el flujo. Vamos a
dar un repaso rápido por las opciones.

● Delete​: elimina el flujo y todos los nodos que tenga dentro.


● Name​: es el nombre del flujo.
● Status​: habilita o deshabilita el flujo. Cuando está deshabilitado no ejecuta ningún
nodo.
● Descripción​: la descripción de lo que hace el flujo.

177
De momento lo único que vamos a hacer es cambiar el nombre. Yo he puesto ​Control
Sonoff​. Una vez que lo tengas haz click en ​Done​.

Es importante recalcar que cada flujo es como si fuera un programa diferente es decir, se
ejecuta en un hilo a parte. Si lo deshabilitas ya no ejecutará ese flujo. Sin embargo, todos
comparten el mismo Dashboard.

Esto quiere decir que podemos tener un flujo para controlar la temperatura y la humedad y
otro flujo para controlar el relé Sonoff por ejemplo. Luego en la misma interfaz web puedes
ver toda la información.

Es sólo una aclaración, vamos a continuar con el control del relé.

Lo primero que vamos a hacer es arrastrar un nodo ​mqtt​ del grupo ​Input​.

Haz doble click sobre el nodo una vez lo hayas arrastrado al flujo para configurar.

La configuración es muy parecida a la que hemos visto en el caso de NodeMCU.

178
El ​Server es el mismo que teníamos configurado ya en Node-RED. Vamos a utilizar el
mismo broker.

Este nodo es el que recibirá los mensajes que se envían desde el relé Sonoff con el estado
en el topic ​casa/despacho/estadorele​.

Como ya te dije, es importante saber en qué estado está para poderlo mostrar en la interfaz
web. Cada vez que se accione de forma manual, se actualizará en la interfaz web de forma
automática.

Pon un nombre descriptivo y haz click en ​Done​. Ya tenemos nuestro primer nodo
configurado.

Ahora tenemos que añadir un nodo para mostrar la información en la interfaz gráfica. Ya
hemos visto el nodo ​switch del grupo ​dashboard​. Además añade un nodo ​debug del grupo
output​.

179
No te olvides de conectar los nodos como aparece en la imagen. Ahora vamos a configurar
el nodo ​switch​. Haz doble click sobre el nodo.

180
En las opciones del nodo ​switch​ vamos a modificar los siguientes parámetros:

● Group​: selecciona el grupo de la interfaz web donde quieres mostrar el nodo. Como
habíamos creado ya grupos y layouts, estos no se eliminan cuando eliminamos los
nodos. Se mantienen hasta que eliminemos los layouts o los grupos. En este
ejemplo añadimos el nodo ​switch​ al grupo ​Luz​ que pertenece al layout​ Casa​.
● Label​: este es el texto que aparecerá en la interfaz gráfica, pon el que tu quieras.
● Indicador​: de momento, sólo hemos añadido un nodo ​mqtt que recibe el mensaje del
relé Sonoff cuando se cambia el estado de forma manual a través del pulsador. Sin
embargo, también queremos que cuando cambiemos el ​switch en la interfaz web, el
relé cambie de estado. Por eso es importante desmarcar el check donde pone ​if msg
arrives on input, pass through to output​. Esto quiere decir que cuando reciba un

181
mensaje el nodo ​switch lo envíe a la salida. No queremos que lo haga ya que en la
salida, tendremos otro nodo ​mqtt y esto haría que entrara en un bucle infinito.
Recibe un mensaje y lo vuelve a enviar al relé Sonoff.
Además, debemos seleccionar la opción ​Switch icon shows state of the output para
que siempre esté actualizado el nodo ​switch​.
● Payload​: como vimos en el ejemplo de NodeMCU, podemos cambiar el valor del
Payload que se envía cuando se activa o desactiva el ​switch​. Vamos a enviar un 1
cuando esté ​on y un 0 cuando esté ​off en formato texto. Luego nos servirá para
enviarlo vía MQTT al relé Sonoff.

Es importante entender qué hemos hecho con esta configuración. Lo que estamos haciendo
es suscribirnos al topic ​casa/despacho/estadorele para obtener el estado del relé cuando se
pulsa el pulsador de forma manual.

Es decir, si ahora conectas el relé a la red eléctrica y aprietas el pulsador, verás como en la
interfaz web se actualiza el estado.

Pero antes sólo nos queda dar al botón ​Done y al botón ​Deploy para actualizar el flujo. Abre
también la interfaz gráfica accediendo a la url.

http://192.168.0.167:1880/ui/

Sustituye la IP por la IP de tu Raspberry Pi o puedes acceder dando al botón en el panel


Dashboard​.

Por defecto estará apagado.

182
Si ahora aprietas el pulsador del relé Sonoff, verás como se activa el ​switch​.

Ya tenemos sincronizado el relé con la interfaz web.

Como hemos añadido un nodo ​debug puedes ver los mensajes que están llegando a
Node-RED.

183
Sin embargo, si accionas el ​switch de la interfaz web verás que el relé Sonoff no cambia de
estado.

Esto es debido a que no estamos publicando ningún mensaje en el topic al que está suscrito
el relé Sonoff. Vamos a cambiar esto añadiendo un nuevo nodo al flujo.

Necesitamos el nodo ​mqtt​ del grupo ​output​ y conectarlo al ​switch​.

Abre las opciones haciendo doble click sobre el nodo.

184
Selecciona el ​Server ​MQTT que tendrás ya configurado. Pon el topic ​casa/despacho/rele
que es donde está suscrito el relé Sonoff y un nombre descriptivo en ​Name​.

El ​QoS ​y el ​Retain lo puedes dejar como está. Ahora haz click en el botón ​Done y no te
olvides del botón ​Deploy​.

Bien, pues ya podemos controlar el relé Sonoff desde la interfaz web ya sea desde un
ordenador o desde un móvil o tablet.

Prueba también a que desde el pulsador del relé Sonoff actualizas el estado en la interfaz
web.

Con esto ya hemos automatizado una lámpara pero podemos hacer mucho más. Puedes
probar a utilizar una resistencia LDR para encender o apagar la luz por ejemplo.

Los límites los ponemos nosotros.

185
Anexo 1: Importar o exportar nodos
En Node-RED podemos importar o exportar nodos desde el menú principal. Los nodos se
guardan en formato JSON.

Exportar nodos
Se pueden exportar nodos de dos maneras, exportar a un archivo o la librería de
Node-RED.

Partimos de este flujo por ejemplo, el del relé Sonoff.

Selecciona todos los nodos. Esto se hace haciendo click en cualquier parte del editor y
arrastrando hasta seleccionar todos los nodos.

Se marcarán todos los nodos con un borde naranja.

186
Ahora ves al menú principal a la opción ​Export donde aparecerán dos opciones: ​Clipboard ​y
Library​.

Vamos a empezar por ​Clipboard​. Si seleccionas la opción se abría una ventana flotante.

187
En esta ventana flotante vas a poder copiar el JSON del flujo o de los nodos. Hay diferentes
opciones.

Si sólo quieres seleccionar los nodos seleccionados debes seleccionar la primera opción,
selected nodes​.

188
Esta opción sólo exporta los nodos que hayas seleccionado. Aquí también se incluye el
broker MQTT y los elementos del ​dashboard​ que se estén utilizando con estos nodos.

Las dos opciones que tienes en la parte de abajo del cuadro de texto te permiten exportar el
JSON compacto (​compact​) o formateado (​formatted​).

Si ahora le das al botón de ​Export to clipboard te copiará el código JSON al portapapeles y


lo podrás guardar en un archivo en tu ordenador. Da lo mismo la extensión que tenga.

189
Si por el contrario quieres guardar todo el flujo de trabajo selecciona la segunda opción,
current flow​.

La diferencia con la opción ​selected nodes es que con esta opción también exportas las
configuración del nodo es decir, el nombre y la descripción.

190
Si das a ​Export clipboard y comparas los dos JSON verás como ha añadido información del
flujo al archivo.

La tercera opción, ​all flows​, exporta todos los flujos que tengas en Node-RED.

191
Esta opción sirve para hacer una copia de todo el sistema por ejemplo.

Pero si lo que queremos es que se Node-RED gestiones los flujos a través de su librería,
tenemos que escoger la opción ​Library​.

Esto abre una nueva ventana flotante donde sólo tenemos que poner una ruta. Por ejemplo
si pones casa/despacho/luz, creará una carpeta casa, dentro una carpeta despacho y
dentro el archivo luz que contiene los nodos seleccionados.

Elegir una opción un otra ya depende de cómo queramos organizar las copias de nuestros
flujos. Yo recomiendo siempre tener al menos una copia de los flujos en algún archivo.

Importar nodos
Ahora vamos a ver cómo podemos importar los nodos. Dependerá de si lo hemos guardado
en un archivo o en la librería de Node-RED.

Selecciona la opción de ​Clipboard.

192
Esto abre una ventana flotante donde puedes pegar el JSON que quieres importar.

Lo puedes importar en el flujo actual seleccionando ​current flow o en un nuevo flujo, ​new
flow​, esto creará un nuevo flujo.

Una vez que lo tengas le das al botón de ​Import​.

Ahora tendrás todos los nodos seleccionados para que hagas click donde quieras y
añadirlos al flujo.

193
Ya tendrías los nodos listos para usar.

La otra opción es importar desde ​Library​.

Verás que se han creado varias opciones según la ruta que hemos generado al exportar los
nodos. Aquí estarían todos los que vayamos exportando a ​Library​.

Estas dos acciones, importar y exportar, te permiten tener copias de los nodos.

Por último existe una tercera opción para importar y es utilizar los ejemplos que vienen
preinstalados en Node-RED.

194
Prueba a abrir los ejemplos y ver que hacen.

195
Anexo 2: Configuración de Node-RED
Existe la posibilidad de personalizar parte de la interfaz gráfica y atajos de teclado de
Node-RED. Esto lo hacemos a través de la opción del menú principal ​Settings.

Esto abre un nuevo panel donde podemos configurar Node-RED. La primera pestaña es
View​.

196
La opción de ​Show grid muestra una rejilla en el área de trabajo del flujo. La opción ​Snap to
grid hace que cuando estemos moviendo los nodos por el área de trabajo del flujo, se
adapten a la rejilla. La opción ​Grid size​ es el tamaño de la rejilla.

197
La opción ​Keyboard permite definir los atajos de teclado. Ya hay algunos definidos por
defecto pero podemos definir los nuestros propios.

Por ejemplo, es interesante tener un atajo de teclado para hacer ​Deploy ya que es una
acción que vamos a hacer muy a menudo. Este atajo de teclado no está definido.

198
Haz click sobre la opción ​Deploy​ y te permitirá editar el atajo para asignar uno.

En el cuadro de texto tienes que poner la combinación de teclas separadas por un guión (-).
Luego puedes elegir entre ​global,​ para que se aplique a todas las instancias de Node-RED
o ​workspace​ para que sólo se aplique a un espacio de trabajo.

Cuando lo tengas todo listo, da al botón del check y se guardará el atajo de teclado para
esta acción.

La última opción es ​Palette que ya la hemos visto. Sirve para gestionar, añadir y quitar los
grupos de nodos que tenemos en Node-RED.

199
En la pestaña de ​Nodes están todos los nodos y grupos de nodos instalados. Puedes
eliminar o deshabilitar los que no necesites.

200
En la pestaña de ​Install puedes instalar nuevos nodos que hay en el repositorio, sólo tienes
que buscar y cuando encuentre instalar.

Espero que te haya gustado esta guía y cualquier sugerencia puedes enviarla a mi correo
personal ​ldelvalleh@programarfacil.com

201

Вам также может понравиться