Registro de alarmas en SQLite con Node-RED
En este artículo vamos a ver cómo implementar un sistema real de registro de alarmas utilizando:
- Node-RED
- SQLite
- Tratamiento de filtros y generación de vistas en DB Browser
Esto que vamos a tratar a continuación forma parte de un proyecto de monitorización de nivel de líquidos en depósitos, el cual se supervisa de manera remota el estado en tiempo real del sistema, genera notificaciones por Telegram y almacena eventos en una base de datos para su posterior análisis mediante informes y gráficas comparativas.
1. Creación de la base de datos en Node-RED

El primer paso es crear la tabla donde se almacenarán las alarmas.
Nodo Function → SQL CREATE
msg.topic = `CREATE TABLE IF NOT EXISTS alarmas_nivel (
id INTEGER PRIMARY KEY AUTOINCREMENT,
rebose TEXT,
falta_agua TEXT,
currentdate TEXT,
currenttime TEXT
);`;
return msg;
Este nodo se conecta directamente al nodo SQLite y actúa como un nodo genérico en Node-RED para la creación de bases de datos, por lo que recomiendo reutilizarlo en otros proyectos IoT industriales.
Se ejecuta una sola vez y crea la tabla si no existe, activándose mediante el injector "Crear tabla alarmas_nivel".
1.1 Lógica de generación de alarmas
Aquí está la parte importante del sistema.
La lógica hace lo siguiente:
- Recibe datos del sensor (
distancia_cm) (no es objeto de este blog) - Evalúa condiciones:
- Rebose
- Falta de agua
- Espera 10 segundos
- Verifica que la condición sigue activa
- Genera el evento SOLO si es real
La parte más importante, y en la que nos vamos a centrar es en esta:
if (tipo === "rebose") {
node.send({
payload: {
rebose: "ON",
falta_agua: "OFF",
currentdate: ts.currentdate,
currenttime: ts.currenttime
}
});
}
Si nos fijamos, este código genera un payload que es el que captará el nodo Función SQL INSERT alarmas_nivel que veremos a continuación y que junto con este formará parte de los nodos necesarios para generar una base de datos.
1.2 Inserción de datos en SQLite
Una vez generada la alarma, se inserta en la base de datos, correspondiente al nodo

En este caso, y tal como se observa, le indicamos la ruta dentro del servidor linux, así como el nombre de la base de datos (nivel_líquidos.bd).
Obviamente, después de creada comprobaremos que dicho archivo aparezca en la carpeta señalada.
1.3 Nodo Function → SQL INSERT
La forma básica que se suele usar para estos casos mantiene siempre la misma estructura, y es la siguiente:
msg.topic = `INSERT INTO alarmas_nivel (rebose, falta_agua, currentdate, currenttime)
VALUES ('${msg.payload.rebose}', '${msg.payload.falta_agua}', '${msg.payload.currentdate}', '${msg.payload.currenttime}');`;
return msg;
El payload generado en de la variable "rebose" nos indicará cuando el líquido haya superado la parte más alta del depósitoc, "falta_agua" indicará cuando el depósito esté totalmente vacío (por tanto habrá fallado la bomba de llenado), y las variables currentdate y currenttime indicarán la fecha y hora.
En conclusión este fragmento de código genera un objeto payload que será recibido por el nodo "SQL INSERT alarmas_nivel", el cual se encargará de construir la consulta SQL y almacenar el evento en la base de datos.
1.4 Verificación con nodo DEBUG
Después del nodo SQLite, se añade un nodo DEBUG.

Con el que nos mostrará y comprobará que los nodos anteriores funcionan bien, que el evento se ha generado correctamente, que los datos son coherentes y que la base de datos está recibiendo información.
Ejemplo de salida:
INSERT INTO alarmas_nivel (rebose, falta_agua, currentdate, currenttime)
VALUES ('ON', 'OFF', '2026-04-26', '15:42:10');
2. Visualización de la base de datos y creación de vistas en SQLite
Una vez que el sistema está funcionando y Node-RED empieza a insertar eventos, lo primero que debemos hacer es comprobar que esos datos realmente se están almacenando correctamente.
Para ello utilizamos DB Browser for SQLite, que es una herramienta muy sencilla que permite ver, filtrar y trabajar con la base de datos sin necesidad de programar.
Antes de nada, lo que haremos es entrar en el servidor y descargar a nuestro disco duro el archivo nivel_liquidos.db para aplicar filtros y generar vistas y tablas virtuales para facilitar el posterior tratamiento de datos. Una vez "mejorado" el archivo volveremos a volcarlos al servidor para que a partir de entonces, todos los inputs se vean reflejados en todas las vistas creadas.
2.1 Visualización de la tabla alarmas_nivel

Al abrir la base de datos (nivel_liquidos.db) y seleccionar la tabla alarmas_nivel, nos encontramos con algo como esto:
- Cada fila representa un evento confirmado
reboseindica si ha habido desbordamientofalta_aguaindica si el depósito ha estado en nivel bajocurrentdateycurrenttimeguardan el momento exacto (fecha y hora)
Aquí es importante entender una cosa:
cada registro es un evento, no un estado continuo.
Es decir, no estás guardando “cómo está el depósito”, sino “qué ha pasado y cuándo”. Digamos por tanto que esta tabla es la tabla original matriz que genera Node-Red, y esto es clave entenderlo para todo lo que viene después.
El problema: así en bruto los datos no sirven para mucho
Si te quedas solo con esta tabla, puedes verla, sí… pero analizarla es incómodo, ya que:
- No tienes una columna clara que diga el tipo de alarma
- Tienes dos columnas (
reboseyfalta_agua) que funcionan como flags - No tienes una fecha completa unificada (está separada en fecha y hora)
Y esto es bastante típico en sistemas industriales donde los datos se guardan “rápido y fiable”, no de forma bonita.
Por eso ahora vamos a transformarlos haciendo uso de la pestaña:
“Ejecutar SQL”
En DB Browser tienes una pestaña llamada “Ejecutar SQL” donde puedes escribir consultas directamente contra la base de datos.
2.2 Crear una vista: vista_alarmas
Una vista es, básicamente, una “tabla virtual”. No duplica datos, simplemente los reorganiza para trabajar mejor con ellos.
En nuestro caso lo que hacemos es crear una llamada vista_alarmas, que hace justo eso.
La idea es transformar esto:
rebose = ON / OFF
falta_agua = ON / OFF
en algo mucho más claro como:
tipo_alarma = REBOSE o FALTA_AGUA
Esto es lo que se ejecuta en “Ejecutar SQL”:
CREATE VIEW vista_alarmas AS
SELECT
id,
'REBOSE' AS tipo_alarma,
datetime(currentdate || ' ' || currenttime) AS fecha_hora,
currentdate,
currenttime
FROM alarmas_nivel
WHERE rebose = 'ON'UNION ALLSELECT
id,
'FALTA_AGUA' AS tipo_alarma,
datetime(currentdate || ' ' || currenttime) AS fecha_hora,
currentdate,
currenttime
FROM alarmas_nivel
WHERE falta_agua = 'ON';
¿Qué está pasando aquí?
Este SQL hace dos cosas: Primero, coge todos los eventos donde hay rebose y les pone una etiqueta fija: "REBOSE". Después, coge todos los eventos donde hay falta de agua y les pone "FALTA_AGUA".
Y finalmente los une con UNION ALL.
Además, construye una columna nueva llamada fecha_hora, juntando la fecha y la hora en un único campo. Esto es muy importante porque permite ordenar y filtrar correctamente en el tiempo.
Como resultado tenemos una tabla mucho más útil, ya que cuando seleccionas la vista vista_alarmas, ahora ves algo como:
- Una columna clara con el tipo de alarma
- Una fecha completa (
fecha_hora) - Los eventos ya clasificados
2.3 Primer filtro útil: ver solo un tipo de alarma
Si lo que queremos es ver solo los eventos de rebose:
SELECT *
FROM vista_alarmas
WHERE tipo_alarma = 'REBOSE';
Y si queremos seleccionar solo falta de agua:
SELECT *
FROM vista_alarmas
WHERE tipo_alarma = 'FALTA_AGUA';
2.4 Filtrar por rango de fechas
Esto es algo que se usa constantemente. Por ejemplo, ver solo los eventos de marzo de 2026:
SELECT *
FROM vista_alarmas
WHERE fecha_hora BETWEEN '2026-03-01 00:00:00' AND '2026-03-31 23:59:59';
Aquí es donde se ve por qué hemos creado fecha_hora ya que si no se hiciera, filtrar sería mucho más complicado.
2.5 Ordenar eventos en el tiempo
Para ver los eventos más recientes primero:
SELECT *
FROM vista_alarmas
ORDER BY fecha_hora DESC;
Ejemplo práctico real (esto es lo que le gusta a un gerente)
Imagina que alguien te pregunta:
“¿Cuántas veces ha habido falta de agua este año?”
SELECT COUNT(*) AS total_falta_agua
FROM vista_alarmas
WHERE tipo_alarma = 'FALTA_AGUA'
AND fecha_hora >= '2026-01-01 00:00:00';
Eso ya no es “datos, sino información.
2.6 Qué hemos conseguido con esto
Sin tocar Node-RED, sin cambiar el sistema, simplemente trabajando sobre la base de datos:
- Hemos convertido datos crudos en información útil
- Hemos creado una estructura reutilizable (la vista)
- Hemos facilitado el análisis
Y esto es exactamente lo que diferencia un sistema que “guarda cosas” de uno que realmente sirve para tomar decisiones.
DB Browser for SQLite da mucho juego, ya que puedes exportar todo esto en formatos .csv o .json. El siguiente paso sería tratar estos datos con algún tipo de aplicación tipo Excel, Power BI, o incluso automatizar informes con Python, pero eso ya sería objeto de otro artículo.
Te dejo el archivo original para que lo "trastees" a tu gusto, asi como los archivos en .csv por si no quieres instalarte el programa y puedas tratar estos datos directamente en excel por ejemplo.
👉 Descarga Plantilla nivel liquidos
Para cualquier duda o si quieres implementar algo similar, puedes escribirme a info@plc32control.com.
También tienes un proyecto completo para que veas como queda en el módulo 04
Primera consulta sin compromiso.
Cuéntame qué equipo tienes y qué quieres controlar o medir.