¿Qué es Node-RED?
Node-RED es una herramienta poderosa para construir aplicaciones y servicios IoT. Su génesis se desencadenó precisamente por esta necesidad de crear rápidamente prototipos de aplicaciones IoT. Un proyecto de código abierto liderado por el grupo de Tecnologías Emergentes de IBM, en particular los dos investigadores, Nick O’Leary y Dave Conway-Jones, Node-RED fue inicialmente una herramienta para ellos mismos mientras trabajaban en proyectos IoT y “buscaban una manera de simplificar el proceso de conectar sistemas y sensores al construir tecnologías de prueba de concepto para clientes.”
En este artículo, utilizaremos tanto los nodos MQTT de Ubidots como las bibliotecas HTTP y MQTT nativas de Node-RED ("nodos") para leer/enviar datos desde/hacia Ubidots.
1. Instalación de los nodos MQTT de Ubidots
Una vez que Node-RED esté en funcionamiento en tu computadora, dirígete al menú en la parte superior derecha y haz clic en la opción 'Manage pallets'. Aparecerá una ventana, como se muestra a continuación. Ve a la pestaña 'Install', busca 'ubidots' e instala los nodos llamados 'ubidots-nodered'.
Finalmente, cierra y vuelve a abrir Node-RED. Ahora deberías ver los nodos MQTT de Ubidots en la sección de entrada y salida, respectivamente, que se encuentran en el panel izquierdo de Node-RED.
NOTA: Por defecto, los nodos MQTT de Ubidots utilizan QoS 1.
2. Uso de los nodos MQTT de Ubidots
Nodo de publicación MQTT de Ubidots
Como su nombre lo sugiere, este nodo publica datos en Ubidots. La siguiente es una configuración típica para el nodo:
Donde:
Tipo de cuenta define el broker al que se enviarán los datos: Ubidots.
Nombre se refiere al nombre del nodo [opcional].
Token de tu cuenta de Ubidots. Puede ser un Token de Cuenta o un Token Organizacional [requerido].
Etiqueta del Dispositivo: La etiqueta del Dispositivo al que se publicarán los datos. Puede enviarse dinámicamente en el objeto JSON del mensaje de entrada con la clave: "ubidotsDeviceLabel". Si no se envía ninguna etiqueta de Dispositivo, tomará el valor predeterminado del campo Etiqueta del Dispositivo. Ten en cuenta que la Etiqueta del Dispositivo es obligatoria.
TLS: Por defecto, todos los datos enviados están encriptados vía TLS. Desmarca si los datos deben ser enviados sin encriptar.
El nodo acepta los siguientes parámetros como entrada:
msg.payload: Contiene el cuerpo del mensaje. En este caso, los valores que se publicarán en el Dispositivo dado en formato JSON. Cada clave es la etiqueta de la variable.
msg.payload.ubidotsDeviceLabel: La etiqueta del Dispositivo al que se publicará el paquete. Si no se envía una Etiqueta del Dispositivo, toma la Etiqueta del Dispositivo del campo Etiqueta del Dispositivo en la configuración del nodo.
Ejemplo de Publicación: El siguiente arreglo simple de nodos publica valores de Temperatura, Humedad y Presión en un Dispositivo de Ubidots llamado “Machine_1”:
El ejemplo utiliza nodos de inyección para enviar valores fijos y un nodo de función para construir la carga útil JSON aceptada por la plataforma. A la derecha, justo debajo del nodo de salida de Ubidots, hay un nodo de depuración que ayuda a inspeccionar la carga útil de salida, como se muestra a continuación:
Aquí está la versión para el portapapeles del ejemplo de publicación para que puedas importarlo fácilmente en tu proyecto de Node-RED.
[{"id":"c365b578.54a618","type":"inject","z":"99b17f5d.db16","name":"Temperature","topic":"temperature","payload":"58","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":270,"y":140,"wires":[["2403cd9b.1b5802"]]},{"id":"daf81333.2a9aa","type":"inject","z":"99b17f5d.db16","name":"Humidity","topic":"Humidity","payload":"47","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":260,"y":180,"wires":[["2403cd9b.1b5802"]]},{"id":"452f88ba.1f1488","type":"inject","z":"99b17f5d.db16","name":"Pressure","topic":"pressure","payload":"60","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":260,"y":220,"wires":[["2403cd9b.1b5802"]]},{"id":"2403cd9b.1b5802","type":"function","z":"99b17f5d.db16","name":"function","func":"var label = msg.topic;\nvar value = msg.payload;\n\nmsg.payload = {\n [label]: value\n};\n\nmsg.payload.ubidotsDeviceLabel = \"Machine_1\";\n\nreturn msg;","outputs":1,"noerr":0,"x":520,"y":180,"wires":[["391d78a3.4a1418","a52cd0b9.af8af"]]},{"id":"391d78a3.4a1418","type":"debug","z":"99b17f5d.db16","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":690,"y":240,"wires":[]},{"id":"a52cd0b9.af8af","type":"ubidots_out","z":"99b17f5d.db16","name":"","token":"YOUR-UBIDOTS-TOKEN","label_device":"","device_label":"Machine_x","tier":"business","tls_checkbox":true,"x":690,"y":180,"wires":[]}]
Nodo de Suscripción MQTT de Ubidots
Como su nombre lo sugiere, este nodo se suscribe a variables o temas (máximo 10). La siguiente es una configuración típica para el nodo:
Donde:
Tipo de cuenta define el broker al que se enviarán los datos: Ubidots.
Nombre se refiere al nombre del nodo [opcional].
Token de tu cuenta. Puede ser un Token de Cuenta o un Token Organizacional.
Etiqueta del Dispositivo: La etiqueta del Dispositivo al que se publicará el paquete. Ten en cuenta que este campo se ignora en caso de que se usen temas personalizados.
TLS: Por defecto, todos los datos se envían encriptados a través de TLS. Desmarca si los datos deben ser enviados sin encriptar.
Usar Temas Personalizados: Habilita la suscripción a temas personalizados, deshabilitando así la suscripción a variables.
Etiquetas de Variables/Temas Personalizados: Si la opción “Usar Temas Personalizados” está deshabilitada, debes ingresar la etiqueta de la Variable a la que el nodo se suscribirá. De lo contrario, debes ingresar el tema en el siguiente formato:
Etiqueta_Dispositivo/Etiqueta_Variable
. Opcionalmente/lv
se puede agregar para suscribirse solo al Último Valor. Los temas admiten caracteres comodín: "+" para un solo nivel y "#" para múltiples niveles.Último Valor de la variable. Solo disponible cuando la opción “Usar Tema Personalizado” está deshabilitada.
Agregar Variable/Agregar Tema: Agregar una variable/tema adicional (hasta 10).
La salida es un objeto JSON con la etiqueta de la variable como clave y el Último Valor/Objeto Dot como valor, por ejemplo:
{"variable_label": {"value": 100, "timestamp": 1583523586668, "context": { "key1": "value1", "key2": "value2"}, "created_at": 1583523586732}
Ejemplo de suscripción a variables: El siguiente arreglo de nodos se suscribe al último valor de la Temperatura, a la variable de Humedad y a la variable de Presión, todas ellas de un dispositivo de Ubidots llamado “Machine_1”:
El ejemplo utiliza un nodo de función para dividir 3 variables en salidas individuales. De esa manera, puedes manejarlas por separado. La siguiente imagen muestra la respuesta del objeto JSON cuando las variables reciben una actualización.
Aquí está la versión para el portapapeles para que puedas importarla fácilmente en tu proyecto de nodos.
[{"id":"a7bea0eb.9b358","type":"function","z":"99b17f5d.db16","name":"function","func":"const varLabels = [\n \"temperature\",\n \"humidity\",\n \"pressure\"\n ];\n \nvar payload = msg.payload;\nvar label = Object.keys(payload)[0];\nvar output = [];\nvarLabels.forEach(function (varLabel){\n if (label == varLabel) {\n msg.payload = payload[label].value;\n output.push(msg);\n } else {\n output.push(null);\n }\n});\n\nreturn output;","outputs":3,"noerr":0,"x":460,"y":480,"wires":[["1a30a1cc.46933e"],["563aac2d.eb64b4"],["2a5f0a3a.a77b46"]]},{"id":"1a30a1cc.46933e","type":"debug","z":"99b17f5d.db16","name":"Temperature","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":650,"y":440,"wires":[]},{"id":"563aac2d.eb64b4","type":"debug","z":"99b17f5d.db16","name":"Humidity","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":640,"y":480,"wires":[]},{"id":"2a5f0a3a.a77b46","type":"debug","z":"99b17f5d.db16","name":"Pressure","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":640,"y":520,"wires":[]},{"id":"3173299f.902716","type":"ubidots_in","z":"99b17f5d.db16","tier":"business","name":"Ubidots in","token":"YOUR-UBIDOTS-TOKEN","device_label":"machine_1","tls_checkbox_in":true,"custom_topic_checkbox":false,"label_variable_1":"temperature","label_variable_2":"humidity","label_variable_3":"pressure","label_variable_4":"","label_variable_5":"","label_variable_6":"","label_variable_7":"","label_variable_8":"","label_variable_9":"","label_variable_10":"","checkbox_variable_1_last_value":true,"checkbox_variable_2_last_value":false,"checkbox_variable_3_last_value":false,"checkbox_variable_4_last_value":true,"checkbox_variable_5_last_value":true,"checkbox_variable_6_last_value":true,"checkbox_variable_7_last_value":true,"checkbox_variable_8_last_value":true,"checkbox_variable_9_last_value":true,"checkbox_variable_10_last_value":true,"x":260,"y":480,"wires":[["a7bea0eb.9b358"]]}]
Ejemplo de suscripción a temas: El siguiente arreglo de nodos se suscribe al tema “+/status/lv
” y “machine_2/#
”. Por lo tanto, devolverá cada actualización en variables con la etiqueta “status” sin importar el Dispositivo y cada actualización de variables del Dispositivo Machine 2:
El ejemplo utiliza un nodo de función para dividir ambas salidas de temas en salidas individuales para que puedas manejarlas por separado. La siguiente imagen muestra la respuesta del objeto JSON:
Aquí está la versión para el portapapeles para que puedas importarla fácilmente en tu proyecto de nodos.
[{"id":"77f94f4b.91c54","type":"ubidots_in","z":"99b17f5d.db16","tier":"business","name":"Ubidots in","token":"YOUR-UBIDOTS-TOKEN","device_label":"machine_1","tls_checkbox_in":true,"custom_topic_checkbox":true,"label_variable_1":"+/status/lv","label_variable_2":"machine_2/#","label_variable_3":"","label_variable_4":"","label_variable_5":"","label_variable_6":"","label_variable_7":"","label_variable_8":"","label_variable_9":"","label_variable_10":"","checkbox_variable_1_last_value":true,"checkbox_variable_2_last_value":false,"checkbox_variable_3_last_value":true,"checkbox_variable_4_last_value":true,"checkbox_variable_5_last_value":true,"checkbox_variable_6_last_value":true,"checkbox_variable_7_last_value":true,"checkbox_variable_8_last_value":true,"checkbox_variable_9_last_value":true,"checkbox_variable_10_last_value":true,"x":260,"y":700,"wires":[["cc9719d3.ba4a78"]]},{"id":"cc9719d3.ba4a78","type":"function","z":"99b17f5d.db16","name":"function","func":"var payload = msg.payload;\nvar key = Object.keys(payload)[0]\nvar output;\n\nswitch(key.includes(\"status\")){\n case true:\n output = [msg, null];\n break;\n \n case false:\n output = [null, msg];\n break;\n}\nreturn output;","outputs":2,"noerr":0,"x":460,"y":700,"wires":[["fe1b808a.ecfba"],["92898340.777d4"]]},{"id":"fe1b808a.ecfba","type":"debug","z":"99b17f5d.db16","name":"status","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":630,"y":681,"wires":[]},{"id":"92898340.777d4","type":"debug","z":"99b17f5d.db16","name":"Machine 2 Variables","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":680,"y":721,"wires":[]}]
3. Uso de los nodos HTTP y MQTT nativos de Node-RED
¿Por qué usar bibliotecas nativas en lugar de la biblioteca de Ubidots?
A través de nuestra experiencia e interacción con miles de desarrolladores, Node-RED y Ubidots complementan bien los servicios del otro cuando:
Comprender los conceptos detrás de los protocolos IoT: Trabajar con las bibliotecas nativas de HTTP y MQTT te ayudará a comprender los conceptos detrás de estos protocolos, enriqueciendo tu experiencia en IoT. Usar una biblioteca que envuelve estos protocolos puede ahorrarte líneas de código, pero ocultará conceptos importantes que pueden ser útiles para la resolución de problemas y la escalabilidad de tu proyecto.
Conexión desde cualquier dispositivo/servidor Node-RED: Algunos entornos de Node-RED dificultan la instalación de bibliotecas de terceros. Por ejemplo, si estás ejecutando Node-RED desde un servidor y no eres el administrador y no puedes instalar bibliotecas. Usar bibliotecas ya integradas puede ahorrarte tiempo, dolores de cabeza y costos de desarrollo.
En los ejemplos a continuación, usaremos un "nodo de inyección" para simular datos, pero, por supuesto, en aplicaciones del mundo real, solo necesitas reemplazar este nodo con su fuente de datos real.
Node-RED + Ubidots usando HTTP
Aquí hay un arreglo simple de nodos que envía un valor "corriente" aleatorio, entre 0 y 5, y un valor "voltaje" fijo a un dispositivo Ubidots llamado "node-red":
Toda la magia ocurre en el nodo "función" llamado "Setup Request", que prepara la solicitud según los detalles HTTP esperados de la API de Ubidots:
Aquí está la versión para el portapapeles, para que puedas importarla en tu proyecto - solo copia y pega, si es necesario.
[{"id":"c53b887d.a27888","type":"inject","z":"98e9cf79.a372f8","name":"","topic":"","payload":"","payloadType":"none","repeat":"5","crontab":"","once":true,"x":110,"y":100,"wires":[["90633f9e.bc1a58"]]},{"id":"90633f9e.bc1a58","type":"function","z":"98e9cf79.a372f8","name":"Setup Request","func":"var msg;\ndevice_label = \"Node-RED\";\nubidots_token = \"BBFF-xxxxxxxxxxxxxx\";\nmsg.method = \"POST\";\nmsg.url = \"http://industrial.api.ubidots.com/api/v1.6/devices/\" + device_label + \"/?token=\" + ubidots_token;\nmsg.payload = {\"current\":5*Math.round(Math.random() * 100) / 100,\"voltage\":\"110\"};\nreturn msg;","outputs":1,"noerr":0,"x":275,"y":100,"wires":[["4b95b329.d784c4"]]},{"id":"8cf48dc0.84df7","type":"debug","z":"98e9cf79.a372f8","name":"","active":true,"console":"false","complete":"payload","x":629,"y":100,"wires":[]},{"id":"4b95b329.d784c4","type":"http request","z":"98e9cf79.a372f8","name":"","method":"use","ret":"txt","url":"","x":453,"y":100,"wires":[["8cf48dc0.84df7"]]}]
Node-RED + Ubidots usando MQTT
Aquí hay un ejemplo que publica datos de temperatura en el broker MQTT de Ubidots y se suscribe a la variable actualizada:
Este ejemplo utiliza un nodo de inyección para publicar la carga útil {"temperature":123} en un nodo de publicación MQTT configurado como se especifica en la documentación MQTT de Ubidots, es decir:
Broker de Ubidots:
industrial.api.ubidots.com
Puerto: 1883
Nombre de Usuario: Tu token de Ubidots
Contraseña: Dejar en blanco
Tema de Publicación:
/v1.6/devices/{LABEL_DEVICE}
Tema de Suscripción:
/v1.6/devices/{LABEL_DEVICE}/{VARIABLE_LABEL}/lv
Ten en cuenta que "lv" significa último valor. Esto significa que este tema solo devuelve el último valor de la variable, sin el formato JSON, lo que facilita su análisis si es necesario.
Ingresar todo esto en Node-RED se vería así:
En el nodo de publicación MQTT:
Al hacer clic en el botón de edición del broker:
En el nodo de suscripción MQTT:
Finalmente, aquí está la versión para el portapapeles para que puedas importar fácilmente este ejemplo en tu proyecto:
[{"id":"8765d540.6b6bc8","type":"inject","z":"eb630143.270018","name":"","topic":"","payload":"{\"temperature\":123}","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":"","x":190,"y":200,"wires":[["f3c857d3.8d10c"]]},{"id":"f3c857d3.8d10c","type":"mqtt out","z":"eb630143.270018","name":"","topic":"/v1.6/devices/node-red","qos":"","retain":"","broker":"694beaca.29a254","x":577,"y":201,"wires":[]},{"id":"cc230b36.52f4e8","type":"mqtt in","z":"eb630143.270018","name":"","topic":"/v1.6/devices/node-red/temperature/lv","qos":"2","datatype":"auto","broker":"694beaca.29a254","x":220,"y":331,"wires":[["3e83a146.589e16"]]},{"id":"3e83a146.589e16","type":"debug","z":"eb630143.270018","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":594,"y":330,"wires":[]},{"id":"694beaca.29a254","type":"mqtt-broker","z":"","name":"","broker":"industrial.api.ubidots.com","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]
NOTA: necesitarás configurar el broker MQTT incluso después de pegar la versión del portapapeles anterior.
Otros usuarios también encontraron útil lo siguiente...