Introducción a Node-RED

Fundamentos de JavaScript, formato JSON y comunicación entre nodos

Node-RED Flow

Esta presentación introduce los conceptos básicos de Node-RED, incluyendo los fundamentos de JavaScript necesarios, el formato JSON y cómo se comunican los nodos entre sí.

¿Qué es Node-RED?

Node-RED es una herramienta visual e intuitiva que permite crear programas o APIs directamente desde el navegador.

Es una plataforma de programación "low-code" que facilita la conexión de dispositivos de hardware, APIs y servicios en línea.

Características principales:

  • Interfaz visual basada en flujos
  • Construido sobre Node.js, utilizando JavaScript
  • Amplia biblioteca de nodos predefinidos
  • Fácil de extender con nodos personalizados
  • Ideal para IoT, automatización y prototipado rápido
Node-RED Interface

Casos de uso comunes:

  • Pasarelas de sensores IoT utilizando MQTT
  • Creación de servicios API
  • Automatización de flujos de trabajo
  • Procesamiento y transformación de datos
  • Integración de sistemas heterogéneos

Historia y Arquitectura

Historia:

  • Desarrollado inicialmente en 2013 por Nick O'Leary y Dave Conway-Jones de IBM
  • Proyecto de código abierto desde septiembre de 2013
  • Se unió a la OpenJS Foundation en octubre de 2016
  • Ampliamente adoptado en la comunidad IoT y de automatización

Componentes clave:

  • Nodos: Bloques funcionales que procesan datos
  • Flujos: Conexiones entre nodos que definen el camino de los datos
  • Editor: Interfaz visual para crear y editar flujos
  • Motor de ejecución: Basado en Node.js

Arquitectura:

Node-RED consiste en un motor de ejecución al que apunta un navegador web para acceder al editor de flujo.

Dentro del navegador, se crea la aplicación arrastrando los nodos de la paleta a un espacio de trabajo y conectándolos. Con un solo clic, la aplicación se implementa en el motor de ejecución donde se ejecuta.

Los flujos creados en Node-RED se almacenan utilizando JSON, lo que facilita su importación y exportación, así como el control de versiones.

Fundamentos de JavaScript

JavaScript es el lenguaje de programación que impulsa Node-RED. Es esencial entender sus conceptos básicos para trabajar eficazmente con Node-RED.

Tipos de datos básicos:

  • String: "Hola mundo"
  • Number: 42, 3.14
  • Boolean: true, false
  • Object: {nombre: "Juan", edad: 30}
  • Array: [1, 2, 3, 4]
  • null y undefined

Variables y constantes:

// Variables (pueden cambiar)
let contador = 0;
contador = contador + 1;

// Constantes (no pueden cambiar)
const PI = 3.14159;

Funciones:

// Declaración de función
function sumar(a, b) {
    return a + b;
}

// Función flecha (ES6+)
const multiplicar = (a, b) => a * b;

Operadores comunes:

  • Aritméticos: +, -, *, /, %
  • Comparación: ==, ===, !=, !==, <, >
  • Lógicos: && (AND), || (OR), ! (NOT)

Literales de plantilla con Backticks

¿Qué son los literales de plantilla?

Los literales de plantilla (template literals) son una característica de ES6 que permite crear cadenas de texto con mayor flexibilidad:

  • Se delimitan con backticks (`) en lugar de comillas
  • Permiten strings multilínea sin caracteres especiales
  • Permiten interpolación de expresiones con ${expresión}
  • Son especialmente útiles para generar HTML, JSON o mensajes formatizados

Comparación con strings tradicionales:

// Concatenación tradicional
let nombre = "Juan";
let edad = 30;
let mensaje = "Hola, soy " + nombre + " y tengo " + edad + " años.";

// Con literales de plantilla
let mensajeTemplate = `Hola, soy ${nombre} y tengo ${edad} años.`;

Ventajas en Node-RED:

  • Facilita la creación de mensajes con datos dinámicos
  • Simplifica la generación de JSON para APIs
  • Mejora la legibilidad del código en nodos Function
  • Permite crear HTML dinámico en nodos Template

Ejemplos prácticos:

// Strings multilínea
let html = `
<div class="sensor">
    <h2>Sensor de temperatura</h2>
    <p>Valor: ${temperatura}°C</p>
</div>
`;

// Expresiones en interpolación
let umbral = 25;
let estado = `Temperatura ${temperatura > umbral ? 'alta' : 'normal'}`;

// Uso con objetos
let datos = { valor: temperatura, unidad: "C" };
let jsonStr = `{"temperatura": ${datos.valor}, "unidad": "${datos.unidad}"}`;

Los literales de plantilla son especialmente útiles en Node-RED para formatear mensajes, crear contenido dinámico y generar estructuras JSON de manera más legible y mantenible.

Objetos y Arrays en JavaScript

Objetos:

Los objetos son colecciones de pares clave-valor:

// Creación de un objeto
let persona = {
    nombre: "María",
    edad: 28,
    profesion: "Ingeniera",
    saludar: function() {
        return "Hola, soy " + this.nombre;
    }
};

// Acceso a propiedades
console.log(persona.nombre);        // "María"
console.log(persona["profesion"]);  // "Ingeniera"

// Modificación de propiedades
persona.edad = 29;

Arrays:

Los arrays son listas ordenadas de valores:

// Creación de un array
let numeros = [1, 2, 3, 4, 5];
let mixto = [1, "dos", true, {clave: "valor"}];

// Acceso a elementos
console.log(numeros[0]);  // 1

// Métodos comunes de arrays
numeros.push(6);          // Añade al final
numeros.pop();            // Elimina del final

// Iteración sobre arrays
numeros.forEach(function(numero) {
    console.log(numero * 2);
});

En Node-RED, los mensajes que fluyen entre nodos son objetos JavaScript, generalmente con una propiedad payload que contiene los datos principales.

JavaScript en Node-RED

En Node-RED, JavaScript se utiliza principalmente en los nodos de función para procesar y transformar mensajes.

Ejemplo de nodo función:

// Nodo función para convertir temperatura
function procesarMensaje(msg) {
    // Acceder a la propiedad payload del mensaje
    let temperatura = msg.payload;
    
    // Validar entrada
    if (typeof temperatura !== 'number') {
        node.error("El payload debe ser un número", msg);
        return null;  // No envía ningún mensaje
    }
    
    // Transformar el valor (Celsius a Fahrenheit)
    temperatura = temperatura * 1.8 + 32;
    
    // Actualizar el payload y añadir propiedades
    msg.payload = temperatura;
    msg.unidad = "Fahrenheit";
    msg.timestamp = new Date().toISOString();
    
    // Devolver el mensaje modificado
    return msg;
}

Características especiales:

  • Acceso al contexto: context.get('variable'), flow.get('variable'), global.get('variable')
  • Múltiples salidas: return [msg1, msg2];
  • Envío asíncrono: node.send(msg); y return null;

Formato JSON

¿Qué es JSON?

JSON (JavaScript Object Notation) es un formato ligero de intercambio de datos, fácil de leer y escribir para humanos, y sencillo de analizar y generar para las máquinas.

Características:

  • Independiente del lenguaje de programación
  • Basado en texto plano
  • Fácil de leer y escribir
  • Estructura jerárquica
  • Ampliamente utilizado en APIs web

Ejemplo de JSON:

{
  "nombre": "Juan",
  "edad": 30,
  "activo": true,
  "intereses": ["programación", "IoT"],
  "direccion": {
    "calle": "Calle Principal",
    "numero": 123,
    "ciudad": "Madrid"
  }
}

Tipos de datos en JSON:

  • String: "texto"
  • Number: 42, 3.14
  • Boolean: true, false
  • null: null
  • Object: {...}
  • Array: [...]

JSON vs Objetos JavaScript

Aunque JSON está basado en la notación de objetos de JavaScript, existen diferencias importantes:

Característica JavaScript JSON
Nombres de propiedades Pueden estar sin comillas Deben estar entre comillas dobles
Strings Comillas simples o dobles Solo comillas dobles
Funciones Permitidas No permitidas
Comentarios Permitidos No permitidos
Comas finales Permitidas No permitidas

Conversión entre formatos:

// Objeto JavaScript a JSON (serialización)
let persona = { nombre: "Ana", edad: 28 };
let personaJSON = JSON.stringify(persona);
// Resultado: '{"nombre":"Ana","edad":28}'

// JSON a objeto JavaScript (deserialización)
let personaObjeto = JSON.parse(personaJSON);

JSON en Node-RED

Importancia de JSON en Node-RED:

  • Los mensajes entre nodos son objetos JavaScript
  • Los flujos se guardan como archivos JSON
  • Integración con APIs externas que usan JSON
  • Almacenamiento de configuraciones

El nodo JSON:

Node-RED proporciona un nodo específico para convertir entre cadenas JSON y objetos JavaScript:

  • Convierte automáticamente entre formatos
  • Maneja errores de análisis
  • Puede forzar la conversión a un tipo específico

Ejemplo práctico:

Procesamiento de datos de un sensor recibidos por MQTT:

// Datos recibidos como string JSON
let mensajeJSON = `{
  "dispositivo": "sensor_temp",
  "ubicacion": "sala",
  "lecturas": {
    "temperatura": 23.5,
    "humedad": 45.2
  }
}`;

// Convertir a objeto JavaScript
let datos = JSON.parse(mensajeJSON);

// Acceder a propiedades anidadas
let temperatura = datos.lecturas.temperatura;
let humedad = datos.lecturas.humedad;

// Procesar datos
let tempF = temperatura * 1.8 + 32;

Comunicación entre nodos

Flujo de mensajes:

En Node-RED, los nodos se comunican pasando mensajes de uno a otro a través de sus conexiones.

Características de los mensajes:

  • Son objetos JavaScript
  • Se pasan por referencia (no por valor)
  • Pueden contener cualquier número de propiedades
  • Generalmente tienen una propiedad payload
  • Incluyen un identificador único _msgid

Ejemplo de mensaje:

{
  "_msgid": "12345abc",
  "payload": 23.5,
  "topic": "sensor/temperatura",
  "timestamp": "2025-04-22T15:30:00Z",
  "unidad": "C"
}

Ciclo de vida de un mensaje:

  1. Un nodo de entrada crea un nuevo mensaje
  2. El mensaje se pasa a los nodos conectados
  3. Cada nodo puede modificar el mensaje
  4. El proceso continúa hasta un nodo final

Los mensajes se pasan por referencia, lo que significa que si un nodo modifica una propiedad, todos los nodos posteriores verán esa modificación.

Patrones de comunicación entre nodos

Patrones comunes:

  1. Secuencial: Los nodos se conectan en secuencia lineal
  2. Bifurcación: Un nodo envía mensajes a múltiples caminos
  3. Filtrado: Algunos mensajes se descartan basados en condiciones
  4. Agregación: Múltiples mensajes se combinan en uno

Modificación de mensajes:

Hay varias formas de modificar mensajes:

  • Nodo Change: Para modificaciones simples
  • Nodo Function: Para lógica personalizada
  • Nodos especializados: JSON, XML, CSV, etc.

Ejemplo de nodo Change:

  • Set msg.payload to "nuevo valor"
  • Change msg.payload from "hola" to "adiós"
  • Delete msg.innecesario
  • Move msg.temp to msg.payload.temperatura

Ejemplo de nodo Function:

function procesarMensaje(msg) {
    // Leer el payload actual
    let temperatura = msg.payload;
    
    // Crear un nuevo objeto
    msg.payload = {
        valor: temperatura,
        unidad: "C",
        convertido: temperatura * 1.8 + 32,
        timestamp: new Date().toISOString()
    };
    
    return msg;
}

Ejemplos prácticos

Ejemplo 1: Procesamiento secuencial de datos

// Flujo: [Inject] → [HTTP Request] → [JSON] → [Function] → [Dashboard] → [Debug]

// Nodo Function para procesar datos del clima
function procesarDatosClima(msg) {
    let datos = msg.payload;
    
    // Extraer solo los datos relevantes
    msg.payload = {
        temperatura: datos.main.temp,
        humedad: datos.main.humidity,
        presion: datos.main.pressure,
        ciudad: datos.name,
        timestamp: new Date().toISOString()
    };
    
    return msg;
}

Ejemplo 2: Bifurcación y procesamiento paralelo

// Flujo con múltiples caminos a partir de un mensaje

// Nodo Function con múltiples salidas
function procesarSensor(msg) {
    let temperatura = msg.payload.temperatura;
    let humedad = msg.payload.humedad;
    
    // Crear mensajes separados para cada valor
    let msgTemp = { payload: temperatura, tipo: "temperatura" };
    let msgHum = { payload: humedad, tipo: "humedad" };
    
    // Enviar a diferentes salidas
    return [msgTemp, msgHum];
}

Buenas prácticas

JavaScript en Node-RED:

  • Usar let y const en lugar de var
  • Validar siempre las entradas
  • Manejar errores con bloques try/catch
  • Comentar el código para facilitar mantenimiento
  • Evitar funciones muy largas o complejas

Trabajando con JSON:

  • Validar siempre los datos JSON recibidos
  • Verificar la existencia de propiedades antes de acceder
  • Usar el nodo JSON en lugar de parse/stringify manual
  • Mantener estructuras JSON consistentes

Comunicación entre nodos:

  • Mantener una estructura de mensajes coherente
  • Evitar modificar partes del mensaje innecesariamente
  • Usar el contexto para estado compartido
  • Documentar la estructura esperada de los mensajes
  • Nombrar los nodos de manera descriptiva

Organización de flujos:

  • Usar pestañas para separar funcionalidades
  • Agrupar nodos relacionados
  • Añadir nodos de comentario para documentar
  • Crear subflows para funcionalidades reutilizables
  • Mantener los flujos simples y enfocados

Recursos adicionales

Comunidad y soporte:

Próximos pasos:

  • Instalar Node-RED localmente o en la nube
  • Explorar la biblioteca de nodos adicionales
  • Crear flujos simples y experimentar
  • Conectar con dispositivos IoT o APIs
  • Participar en la comunidad

¡Gracias por asistir a esta introducción a Node-RED! Recuerda que la mejor manera de aprender es practicando y experimentando con tus propios flujos.

Diapositiva 1 de 15