Implementar protocolos industriales comunes como Modbus en Node-RED frecuentemente conduce a la duplicación de código en múltiples nodos Function. Esto influye negativamente en la mantenibilidad y legibilidad del flujo. La solución es encapsular esa lógica reutilizable en un nodo personalizado.
Esta guía técnica detalla el proceso completo para desarrollar, desde cero, un nodo de Node-RED empaquetado como un módulo npm reutilizable. Cubrimos la estructura del proyecto, la definición de la interfaz de usuario, la implementación de la lógica del servidor, y los métodos para probar y publicar el paquete.
- Estructura del Proyecto y Configuración de Paquete
Un nodo personalizado se organiza en un directorio con una estructura específica. El nombre del directorio y del paquete npm normalmente sigue la convención node-red-contrib-*.
mi-nodo-personalizado/
├── package.json
├── README.md
├── nodes/
│ ├── mi-nodo.html
│ └── mi-nodo.js
└── icono.png (opcional)
El archivo package.json es fundamental. Además de los metadatos estándar, debe contener un campo especial que indique a Node-RED la ubicación de los archivos de definición del nodo.
{
"name": "node-red-contrib-mi-nodo",
"version": "0.1.0",
"description": "Descripción concisa de la funcionalidad",
"keywords": ["node-red", "ejemplo", "tutorial"],
"node-red": {
"nodes": {
"mi-nodo": "nodes/mi-nodo.js"
}
}
}
- Diseño de la Interfaz de Configuración (HTML)
El archivo mi-nodo.html contiene dos secciones script. La primera define la plantilla HTML para el panel de configuración que el usuario ve al hacer doble clic en el nodo. La segunda registra el tipo de nodo en Node-RED con sus propiedades.
<script type="text/html" data-template-name="mi-nodo">
<div class="form-row">
<label for="node-input-nombre"><i class="fa fa-tag"></i> Nombre</label>
<input type="text" id="node-input-nombre">
</div>
<div class="form-row">
<label for="node-input-umbral">Umbral Crítico</label>
<input type="number" id="node-input-umbral" value="80">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('mi-nodo', {
category: 'procesamiento',
color: '#F0E68C',
defaults: {
nombre: { value: "" },
umbral: { value: 80, required: true, validate: RED.validators.number() }
},
inputs: 1,
outputs: 1,
icon: "icono.png",
label: function() { return this.nombre || "Mi Nodo"; }
});
</script>
- Lógica del Servidor (JavaScript)
El archivo mi-nodo.js exporta una función que Node-RED invoca. Dentro de ella se define el constructor del nodo, que inicializa el estado y registra los manejadores de eventos, siendo el más importante el evento 'input'.
module.exports = function(RED) {
function MiNodoProcesador(config) {
RED.nodes.createNode(this, config);
const nodo = this;
const nivelCritico = config.umbral;
nodo.on('input', function(mensaje, enviarFn, completarFn) {
try {
const valorEntrada = parseFloat(mensaje.payload);
if (isNaN(valorEntrada)) {
throw new Error("El payload no es un número válido.");
}
const estado = valorEntrada >= nivelCritico ? "alerta" : "normal";
mensaje.payload = {
valorOriginal: valorEntrada,
estadoSistema: estado,
marcaTemporal: Date.now()
};
enviarFn(mensaje);
completarFn();
} catch (err) {
nodo.error("Error en el procesamiento: " + err.message, mensaje);
completarFn(err);
}
});
nodo.on('close', function(hecho) {
// Lógica de limpieza si es necesario
hecho();
});
}
RED.nodes.registerType("mi-nodo", MiNodoProcesador);
}
- Desarrollo Local y Depuración
Para probar durante el desarrollo sin publicar, se puede enlazar el directorio del paquete localmente con npm. Esto permite iterar rápidamente al editar los archivos.
# En el directorio raíz del paquete del nodo
npm link
# Dentro del directorio de configuración de Node-RED (ej. ~/.node-red)
npm link node-red-contrib-mi-nodo
Una vez enlazado, al guardar cambios en mi-nodo.js o mi-nodo.html, basta con recargar la interfaz de Node-RED en el navegador para ver los cambios. Para registrar mensajes de depuración, se puede usar nodo.warn() o console.log, que aparecerán en la consola del terminla donde se ejecuta Node-RED.
- Prácticas Recomendadas y Empaquetado
Al diseñar un nodo, se debe perseguir la cohesión: que realice una tarea bien definida. Proporcione valores predeterminados razonables en la configuración y asegúrese de que los mensajes de error sean descriptivos y contextuales.
Para compartir el nodo, publíquelo en el registro público de npm. Asegúrese previamente de que la versión en package.json sea correcta y que el README.md contenga instrucciones claras de uso.
npm publish
Posteriormente, cualquier usuario de Node-RED podrá instalarlo ejecutando npm install node-red-contrib-mi-nodo desde su directorio de configuración.