En cualquier infraestructura doméstica o profesional, el SAI (Sistema de Alimentación Ininterrumpida) es el guardián silencioso que protege nuestros equipos. Sin embargo, un SAI solo es realmente útil si sabemos exactamente qué está pasando con él en tiempo real.
En este artículo, vamos a configurar un sistema de alertas avanzado utilizando una Raspberry Pi y el software NUT (Network UPS Tools) para convertir un SAI Salicru convencional en un dispositivo inteligente y conectado.
El objetivo es automatizar el control total de nuestra energía mediante un Bot de Telegram que nos mantendrá informados con mensajes detallados y visuales. Al finalizar este tutorial, tu sistema será capaz de:
- Notificar cortes y restablecimientos de corriente de forma instantánea.
- Enviar reportes detallados con voltajes de entrada, salida y estado de la batería.
- Gestionar estados críticos como el nivel de batería bajo o la necesidad de sustitución de celdas (
REPLBATT). - Proteger tu hardware, avisándote justo antes de que la Raspberry Pi realice un apagado controlado para evitar daños en la tarjeta SD.
Todo esto mediante un script optimizado que garantiza que la información que recibes en tu móvil es veraz y estable, permitiéndote tomar decisiones informadas estés donde estés.
Sistema
Como sistema operativo voy utilizar Rasbperry Pi OS lite 64bits, basado en Debian 13. El usuario del sistema será nut y el host será zero.
Materiales necesarios
- RASPBERRY PI ZERO 2W – 2WH (Versión: W (WiFi))
- Un SAI Salicru con puerto USB (Serie SOHO+ o similar).
- CABLE OTG MICROUSB/M USB-A/H NEGRO
- ALIMENTADOR OFICIAL RASPBERRY PI MICRO-USB 5,1V 2,5A 12,75W
- CAJA OFICIAL RASPBERRY PI ZERO
- CABLE USB-A A USB-B M/M AZUL 30CM
Instalación de NUT
Actualizamos la lista de repositorios e instalamos los paquetes oportunos.
sudo apt update && sudo apt install nut nut-client nut-server curl bc -y
Configuración del hardware.
Según el modelo de SAI, nut puede manejar distintos tipos de driver. Antes de configurar el archivo ups.conf conecta el cable USB de la PI al SAI y ejecuta este comando:
sudo nut-scanner -U
Este comando escaneará los buses USB y te dirá exactamente qué driver recomienda NUT para tu dispositivo específico.
nut@zero:~ $ sudo nut-scanner -U
Cannot load SNMP library (libnetsnmp.so.40) : file not found. SNMP search disabled.
Cannot load XML library (libneon.so.27) : file not found. XML search disabled.
Cannot load AVAHI library (libavahi-client.so.3) : file not found. AVAHI search disabled.
Cannot load IPMI library (libfreeipmi.so.17) : file not found. IPMI search disabled.
Scanning USB bus.
[nutdev1]
driver = "nutdrv_qx"
port = "auto"
vendorid = "0665"
productid = "5161"
product = "USB to Serial"
vendor = "Cypress Semiconductor"
bus = "001"
device = "002"
busport = "001"
###NOTMATCHED-YET###bcdDevice = "0002"
Observa que el driver recomendado es «nutdrv_qx«.
Archivos de configuración de NUT
Define el driver, editando el siguiente archivo.
sudo nano /etc/nut/ups.conf
Al comienzo del archivo, pega lo siguiente.
[salicru]
driver = nutdrv_qx
port = auto
vendorid = 0665
productid = 5161
vendor = "Cypress Semiconductor"
product = "USB to Serial"
desc = "Salicru SOHO 2000"
En ese mismo archivo busca la línea maxretry = 3 comentala y déjala así.
#maxretry = 3
Guarda con Crtl + o y cierra con Crtl + x
Configura el modo editando el siguiente archivo.
sudo nano /etc/nut/nut.conf
Busca la línea MODE, cambia la línea a standalone.
MODE=standalone
Configurar el acceso (upsd.conf)
Una vez que el driver está leyendo los datos del USB, necesitamos que el «servidor de NUT» (upsd) recoja esa información y la deje disponible para resto de equipos y otros programas (como nuestro script de Telegram o el comando upsc) puedan consultarla.
Para ello, editamos el archivo de configuración del demonio:
sudo nano /etc/nut/upsd.conf
Este archivo suele tener lineas que apuntan al localhost como las que vemos a continuación.
LISTEN 127.0.0.1 3493
LISTEN ::1 3493
Si las tienes, borralas y deja solo una línea LISTEN tal y como queda en la siguiente instrucción.
LISTEN 0.0.0.0 3493
El 0.0.0.0 sirve para que los demás equipos vean a la Pi Zero.
«Por seguridad, NUT viene configurado para ser ‘tímido’ (127.0.0.1) y solo hablar consigo mismo. Al cambiarlo a 0.0.0.0, convertimos a nuestra Raspberry Pi Zero en un Faro de Energía: ahora cualquier equipo de nuestra red local puede ver el estado del SAI y saber cuándo debe ponerse a salvo.»
¿Qué hace exactamente LISTEN 0.0.0.0?
Cuando configuras LISTEN 0.0.0.0 en el archivo upsd.conf de la Pi Zero, le estás diciendo al servidor NUT: «No te escondas; acepta preguntas de cualquier dirección IP que llegue a esta Raspberry».
- Sin el 0.0.0.0 (solo con 127.0.0.1): La Pi Zero está «sorda» a lo que venga de fuera. Tus equipos intentarán llamarla por red, pero ella no responderá porque solo escucha sus propios pensamientos internos (localhost).
- Con el 0.0.0.0: La Pi Zero abre sus «oídos» a toda la red local. Ahora, cuando el i7 pregunte: «¿Cómo va la batería?», la Pi Zero podrá escucharlo y responderle con los datos del Salicru.
¿Cómo «ve» la Pi Zero a los demás?
Curiosamente, la Pi Zero no necesita «ver» activamente a los demás equipos para protegerlos. Funciona al revés:
- La Pi Zero (Maestro) simplemente publica la información del SAI en la red.
- Los demás equipos (Esclavos como la Pi 5 o el i7) se conectan a ella constantemente para «leer» esa información.
- En el momento en que la Pi Zero detecta batería baja, cambia su estado a
FSD(Forced Shutdown). - Los esclavos, que están vigilando ese estado cada pocos segundos, ven el cambio y deciden apagarse por su cuenta.
Configurar
0.0.0.0es como abrir la ventanilla de información de la Pi Zero al resto de la casa. Permite que tus PCs potentes se conviertan en «clientes» que consultan el estado del SAI a través de la red WiFi o Ethernet.
¿127.0.0.1 vs 0.0.0.0? Entendiendo la «Escucha» de Red
Para que tu estrategia de apagado coordinado funcione, es vital entender qué dirección IP debe usar el servidor NUT. Aquí tienes la comparativa de lo que sucede en tu Raspberry Pi Zero:
Configuración (LISTEN) | Alcance | Seguridad | ¿Cuándo usarla? |
127.0.0.1 (Localhost) | 🔒 Solo Interno. La Pi Zero solo se habla a sí misma. | Máxima. Nadie fuera de la Pi puede ver los datos. | Cuando solo quieres recibir avisos por Telegram desde esa Raspberry. |
0.0.0.0 (Todas las IPs) | 🌍 Toda la Red. La Pi Zero se vuelve visible para el i7, la Pi 5 y el resto de PCs. | Media. Requiere usar contraseñas en upsd.users. | Obligatorio para apagar otros equipos de casa por red. |
Crear la regla de permisos (udev)
La regla de udev es la forma que tiene Linux (en este caso tu Raspberry Pi con Debian) de gestionar los dispositivos que conectas físicamente a los puertos.
Para crear la regla, abre el editor nano con el siguiente comando.
sudo nano /etc/udev/rules.d/99-nut-ups.rules
Pega dentro esta línea exactamente:
SUBSYSTEM=="usb", ATTR{idVendor}=="0665", ATTR{idProduct}=="5161", MODE="0660", GROUP="nut"
(Guarda con Ctrl+O, Enter y sal con Ctrl+X).
Los valores de la regla, los vimos cuando ejecutamos el comando nut-scanner -U de donde extraemos los valores idVendor y idProduct.
Aplicamos la regla con:
sudo udevadm control --reload-rules && sudo udevadm trigger
Como Linux es un sistema multiusuario y seguro, por defecto no permite que cualquier programa (como el software de NUT) «hable» directamente con un hardware USB a menos que seas el administrador (root). La regla de udev que creamos sirve para decirle al sistema: «Cuando veas este SAI de Salicru, dáselo al grupo ‘nut’ para que pueda leer sus datos».
Anatomía de la regla
La línea que pusimos en /etc/udev/rules.d/99-nut-ups.rules se desglosa así:
SUBSYSTEM=="usb", ATTR{idVendor}=="0665", ATTR{idProduct}=="5161", MODE="0660", GROUP="nut"
SUBSYSTEM=="usb": Le dice a Linux que solo mire en los puertos USB.ATTR{idVendor}=="0665": «Busca al fabricante 0665».ATTR{idProduct}=="5161": «Y que el producto sea el 5161».MODE="0660": Esto define los permisos de archivos de Linux.0660significa que el dueño y el grupo pueden leer y escribir, pero el resto del mundo no puede hacer nada.GROUP="nut": Aquí está la magia. Le asigna la propiedad del puerto al gruponut. Como el software de monitorización corre bajo el usuarionut, ahora ya tiene «llave» para entrar al puerto USB.
¿Por qué es necesaria en la Raspberry Pi?
Sin esta regla, cuando el driver nutdrv_qx intenta preguntar al SAI «¿cuánta batería te queda?», el sistema operativo le responde: «Acceso denegado».
Si esta regla no está o está mal aplicada, te saldrá el error insufficient permissions. Al añadir la regla, el permiso se vuelve automático: cada vez que arranques la Raspberry o reconectes el USB, Linux aplicará estas instrucciones al instante.
Sincronizar los servicios
Ejecuta esto para limpiar y arrancar de forma oficial:
sudo systemctl stop nut-monitor nut-server
sudo rm -f /run/nut/*.pid
sudo systemctl start nut-server
sudo systemctl start nut-monitor
Comprobar la comunicación
Ahora, espera unos 5 segundos y lanza:
upsc salicru@localhost
El comando nos muestra en tiempo real la información detallada, el estado y las variables del Sistema de Alimentación Ininterrumpida (SAI/UPS)que está gestionado localmente mediante la herramienta NUT (Network UPS Tools)
nut@zero:~ $ upsc salicru@localhost
Init SSL without certificate database
battery.voltage: 27.4
device.type: ups
driver.debug: 0
driver.flag.allow_killpower: 0
driver.name: nutdrv_qx
driver.parameter.pollfreq: 30
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.parameter.product: USB to Serial
driver.parameter.productid: 5161
driver.parameter.synchronous: auto
driver.parameter.vendor: Cypress Semiconductor
driver.parameter.vendorid: 0665
driver.state: updateinfo
driver.version: 2.8.1
driver.version.data: Q1 0.08
driver.version.internal: 0.36
driver.version.usb: libusb-1.0.28 (API: 0x100010a)
input.frequency: 49.8
input.voltage: 235.2
input.voltage.fault: 235.2
output.voltage: 231.3
ups.beeper.status: enabled
ups.delay.shutdown: 30
ups.delay.start: 180
ups.load: 0
ups.productid: 5161
ups.status: OL
ups.temperature: 25.0
ups.type: offline / line interactive
ups.vendorid: 0665
nut@zero:~ $
Puerto de escucha
Como dato interesante, comprueba si el puerto 3493 que configuramos anteriormente, está a la escucha
nut@zero:~ $ ss -ltn | grep 3493
LISTEN 0 16 0.0.0.0:3493 0.0.0.0:*
Las líneas LISTEN, indican que la Raspberry ya tiene la oreja puesta y está lista para informar sobre el estado del Salicru.
Procesos
Puedes escribir upsutil salicru@localhost o simplemente ver el estado del servicio:
Para verificar si el monitor (upsmon) está funcionando correctamente en tu Raspberry Pi, usa estos comandos:
nut@zero:~ $ ps aux | grep upsmon
root 6906 0.0 0.6 7304 2688 ? Ss 10:05 0:00 /lib/nut/upsmon -F
nut 6907 0.0 1.2 10236 5120 ? S 10:05 0:03 /lib/nut/upsmon -F
nut 9598 0.0 0.4 8804 2064 pts/0 S+ 21:39 0:00 grep --color=auto upsmon
nut@zero:~ $
Deberías ver 3 procesos: uno que corre como root (el que tiene permiso para apagar la Pi) el otro como el usuario nut y el otro es simplemente el comando que acabamos de escribir.
Comprobar el estado del servicio.
Ejecuta el comando sudo systemctl status nut-monitor
nut@zero:~ $ sudo systemctl status nut-monitor
● nut-monitor.service - Network UPS Tools - power device monitor and shutdown controller
Loaded: loaded (/usr/lib/systemd/system/nut-monitor.service; enabled; preset: enabled)
Active: active (running) since Sat 2026-03-07 22:12:57 CET; 12h ago
Invocation: 95d0260bee1c4eca9ad4a618365a8a2c
Process: 1091 ExecStartPre=/usr/bin/systemd-tmpfiles --create /usr/lib/tmpfiles.d/nut-common-tmpfiles.conf (code=exited, status=0/SUCCESS)
Main PID: 1093 (upsmon)
Tasks: 2 (limit: 176)
CPU: 3.333s
CGroup: /system.slice/nut-monitor.service
├─1093 /lib/nut/upsmon -F
└─1098 /lib/nut/upsmon -F
mar 07 22:12:57 zero systemd[1]: Starting nut-monitor.service - Network UPS Tools - power device monitor and shutdown controller...
mar 07 22:12:57 zero systemd[1]: Started nut-monitor.service - Network UPS Tools - power device monitor and shutdown controller.
mar 07 22:12:57 zero nut-monitor[1093]: fopen /run/nut/upsmon.pid: No such file or directory
mar 07 22:12:57 zero nut-monitor[1093]: Could not find PID file to see if previous upsmon instance is already running!
mar 07 22:12:57 zero nut-monitor[1093]: UPS: salicru@localhost (primary) (power value 1)
mar 07 22:12:57 zero nut-monitor[1093]: Using power down flag file /etc/killpower
mar 07 22:12:57 zero nut-monitor[1098]: Init SSL without certificate database
mar 07 22:12:57 zero nut-monitor[1098]: upsnotify: notify about state 2 with libsystemd: was requested, but not running as a service unit now, will not spam more about it
mar 07 22:12:57 zero nut-monitor[1098]: upsnotify: failed to notify about state 2: no notification tech defined, will not spam more about it
mar 07 22:12:57 zero nut-monitor[1098]: upsnotify: logged the systemd watchdog situation once, will not spam more about it
nut@zero:~ $
Si aparece en verde (active (running)), el vigilante está despierto.
Configurando los avisos por terminal.
sudo nano /etc/nut/upsmon.conf
Pega el siguiente texto debajo
# Banderas para ejecutar el comando (EXEC)
NOTIFYFLAG ONLINE SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL+EXEC
Reinicia el servicio con:
sudo systemctl stop nut-monitor nut-server
Esto dará avisos en la terminal de tu raspberry, pero no lo hará si estas accediendo por ssh.
Cómo configurar el apagado automático (upsmon)
Como nuestra Raspberry Pi Zero 2W está conectada al Salicru, vamos a configurar el sistema para que se apague de forma segura.
Configurar el usuario
Debemos de tener un par de usuarios configurados para la gestión del SAI, que será el usurario administrador [monuser] y el usuario de los equipos remotos que será [remotemon]
Edita el archivo de usuarios de NUT:
sudo nano /etc/nut/upsd.users
Añade esto al final:
[monuser]
password = mi_password_segura
upsmon master
Si quieres, puedes dar a [monuser] privilegios de administrador así:
[monuser]
password = mi_password_segura
upsmon master
actions = SET
instcmds = ALL
Para dar privilegios de administrador a un usuario, tan solo agrégale las directrices actions e instcmds
Para el usuario remoto, añade este perfil al final (usa una contraseña distinta a la de admin):
[remotemon]
password = clave_red_segura
upsmon slave
Configurar el monitor
Edita el archivo del monitor:
sudo nano /etc/nut/upsmon.conf
Busca la sección MONITOR y asegúrate de que quede así:
MONITOR salicru@localhost 1 monuser mi_password_segura master
SHUTDOWNCMD "/sbin/shutdown -h now"
POWERDOWNFLAG /etc/killpower
Activar el servicio
Reinicia todo para que los cambios tengan efecto:
sudo systemctl restart nut-monitor
¿Qué pasará ahora cuando se corte la luz?
Si el SAI se apaga antes de que la Raspberry complete su apagado, podrías tener el mismo problema que con un corte normal de luz, archivos corruptos en la MicroSD. Este sistema está diseñado con una secuencia de retardo muy específica para evitar esto, El Retardo (Delay). Cuando la Raspberry envía la orden de «Kill Power», no le está diciendo al SAI «Apágate ya», sino «Apágate dentro de X segundos».
Si te fijas en los datos de tu upsc salicru@localhost, hay una línea clave:
ups.delay.shutdown: 30
Esto significa que cuando la Raspberry envía la orden final, el SAI Salicru inicia una cuenta atrás interna de 30 segundos.
La Secuencia Cronológica
Para que veas que es seguro, este es el orden real de los eventos:
- Raspberry detecta Batería Baja: Inicia su propio proceso de apagado (
SHUTDOWNCMD). - Cierre de Servicios: Debian detiene bases de datos, logs y procesos. La tarjeta SD deja de escribir datos.
- Script Final de NUT: Justo en el último segundo del apagado (cuando el sistema ya está en modo «solo lectura»), se ejecuta la orden de «Kill Power» hacia el SAI.
- SAI recibe la orden: El Salicru empieza su cuenta atrás de 30 segundos.
- Raspberry muere: La Pi termina de apagarse por completo en 2 o 3 segundos más.
- El SAI se apaga: 27 segundos después de que la Pi ya esté totalmente «muerta», el SAI corta la energía.
¿Por qué es necesario que el SAI se apague?
Imagina que no enviamos el «Kill Power»:
- La Raspberry se apaga y se queda esperando.
- El SAI se queda encendido con batería hasta que se agote al 0%.
- Vuelve la luz de la calle.
- Problema: Como el SAI nunca llegó a cortarle la corriente a la Raspberry (porque se quedó en un estado de «espera» con la batería agotada pero sin apagar el circuito), la Raspberry no detectará que ha vuelto la energía y no arrancará sola. Se quedará apagada hasta que alguien vaya físicamente a desenchufarla y enchufarla.
Resumen de seguridad
Con el valor de 30 segundos que tiene tu Salicru de fábrica:
- La Raspberry tiene tiempo de sobra (le sobran unos 25 segundos) para terminar de cerrarlo todo antes de que el SAI corte el flujo eléctrico.
- Es un método estándar y muy seguro.
Un detalle importante: En las Raspberry Pi, para que el ciclo de «vuelva la luz y se encienda sola» funcione perfecto, asegúrate de que el SAI esté configurado para rearmarse automáticamente (cosa que los Salicru SOHO+ hacen por defecto).
Para estar seguro de que la Raspberry sabe que es la jefa del apagado (modo master), ejecuta:
upsc salicru@localhost ups.delay.shutdown
Si te responde 30, significa que todo está listo para que, en caso de emergencia, la Pi le ordene al Salicru esperar 30 segundos antes de cortar la energía, dándole tiempo a la MicroSD para cerrarse a salvo.
¿Cómo saber si realmente se apagará? (Simulación segura)
Si quieres estar 100% seguro de que la configuración es correcta sin apagar la Raspberry de golpe, puedes mirar el log del sistema:
sudo journalctl -f -u nut-monitor -u nut-server
Si ahora mismo desenchufas el SAI de la pared, Verás en el log UPS salicru@localhost on battery.
nut@zero:~ $ sudo journalctl -f -u nut-monitor -u nut-server
mar 07 18:05:06 zero nut-server[7408]: Instant command: upsmon@::1 did test.battery.start.quick on salicru (tracking ID: disabled)
mar 07 18:05:06 zero upsd[7408]: Instant command: upsmon@::1 did test.battery.start.quick on salicru (tracking ID: disabled)
mar 07 19:24:09 zero nut-server[7408]: Instant command: upsmon@::1 did test.battery.start.quick on salicru (tracking ID: disabled)
mar 07 19:24:09 zero upsd[7408]: Instant command: upsmon@::1 did test.battery.start.quick on salicru (tracking ID: disabled)
mar 07 19:27:08 zero nut-server[7408]: Instant command: upsmon@::1 did test.battery.start.quick on salicru (tracking ID: disabled)
mar 07 19:27:08 zero upsd[7408]: Instant command: upsmon@::1 did test.battery.start.quick on salicru (tracking ID: disabled)
mar 07 20:05:29 zero nut-monitor[6907]: UPS salicru@localhost on battery
mar 07 20:05:45 zero nut-monitor[9348]: Network UPS Tools upsmon 2.8.1
Si miras en upsc salicru@localhost verás que cambia a status: OB.
nut@zero:~ $ upsc salicru@localhost
Init SSL without certificate database
battery.voltage: 26.9
device.type: ups
driver.debug: 0
driver.flag.allow_killpower: 0
driver.name: nutdrv_qx
driver.parameter.pollfreq: 30
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.parameter.product: USB to Serial
driver.parameter.productid: 5161
driver.parameter.synchronous: auto
driver.parameter.vendor: Cypress Semiconductor
driver.parameter.vendorid: 0665
driver.state: quiet
driver.version: 2.8.1
driver.version.data: Q1 0.08
driver.version.internal: 0.36
driver.version.usb: libusb-1.0.28 (API: 0x100010a)
input.frequency: 50.0
input.voltage: 9.6
input.voltage.fault: 9.6
output.voltage: 227.4
ups.beeper.status: enabled
ups.delay.shutdown: 30
ups.delay.start: 180
ups.load: 0
ups.productid: 5161
ups.status: OB
ups.temperature: 25.0
ups.type: offline / line interactive
ups.vendorid: 0665
Lo más importante:
Como el modelo SOHO+ 2000, tiene mucha autonomía para una Raspberry Pi Zero 2W (que consume casi nada). No esperes a que llegue a Low Battery (batería baja) de forma real porque podría tardar horas.
Si en algún momento quieres probar que el apagado funciona de verdad, el comando es:
sudo upsmon -c fsd
(Esto significa «Forced Shutdown» y simula que la batería se ha agotado, iniciando el proceso de apagado de seguridad inmediatamente).
¡Ya está todo listo y protegido! Tu Raspberry Pi ahora sobrevivirá a los cortes de luz sin corromper la tarjeta SD.
El script de alertas para Telegram
Creamos el script que enviará los mensajes:
sudo nano /usr/local/bin/nut-telegram.sh
Copia y pega el siguiente script. No olvides reemplazar «tu_token» y «tu_id» por los tuyos propios
#!/bin/bash
# Configuración del Bot de Telegram
TOKEN="tu_token"
CHAT_ID="tu_id"
export LC_ALL=C
# Función interna para leer los sensores (Lógica estable)
capturar() {
BATERIA_V=$(upsc salicru@localhost battery.voltage 2>/dev/null || echo "0.0")
VOLTAJE_IN=$(upsc salicru@localhost input.voltage 2>/dev/null || echo "0.0")
VOLTAJE_OUT=$(upsc salicru@localhost output.voltage 2>/dev/null || echo "0.0")
CARGA_SAI=$(upsc salicru@localhost ups.load 2>/dev/null || echo "0")
ESTADO_SAI=$(upsc salicru@localhost ups.status 2>/dev/null || echo "N/A")
}
case "$1" in
*"on battery"*)
ICONO="🚨"
TITULO="CORTE DE SUMINISTRO"
# BUCLE DE ESPERA: No envía hasta que la entrada sea < 50V real
intentos=0
capturar
while [[ "${VOLTAJE_IN%.*}" -gt 50 ]] && [[ $intentos -lt 12 ]]; do
sleep 5
capturar
((intentos++))
done
# --- DIAGNÓSTICO DE SALUD AL CORTE ---
V_INT=${BATERIA_V%.*}
if [ "$V_INT" -lt 24 ]; then
DETALLE="¡OJO! Las baterías están muy bajas ($BATERIA_V V). Salud crítica, considera cambiarlas."
else
DETALLE="El SAI está operando con baterías. Salud química OK ($BATERIA_V V)."
fi
;;
*"on line power"*)
ICONO="✅"
TITULO="CORRIENTE RESTABLECIDA"
DETALLE="El sistema vuelve a la red eléctrica."
# BUCLE DE ESPERA: No envía hasta que la entrada sea > 200V real
intentos=0
capturar
while [[ "${VOLTAJE_IN%.*}" -lt 200 ]] && [[ $intentos -lt 12 ]]; do
sleep 5
capturar
((intentos++))
done
;;
*"low battery"*)
ICONO="⚠️"
TITULO="BATERIA CRITICA"
DETALLE="Nivel muy bajo. El apagado es inminente."
capturar
;;
*"SHUTDOWN"*)
ICONO="💀"
TITULO="APAGADO DE EMERGENCIA"
DETALLE="La Raspberry se apaga para proteger la SD."
capturar
;;
*"REPLBATT"*)
ICONO="🛠️"
TITULO="FALLO DE BATERIA"
DETALLE="Es necesario sustituir las baterías del Salicru."
capturar
;;
*)
ICONO="ℹ️"
TITULO="NOTIFICACION SAI"
DETALLE="$1"
capturar
;;
esac
# Mensaje final con los iconos: 🔌 y ⚡
CUERPO="$ICONO *$TITULO* $ICONO
------------------------------------
📝 $DETALLE
🔋 *Bateria:* $BATERIA_V V
🔌 *Entrada:* $VOLTAJE_IN V
⚡ *Salida:* $VOLTAJE_OUT V
📊 *Carga SAI:* $CARGA_SAI%
📈 *Estado:* $ESTADO_SAI"
# Envío a Telegram
curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" \
--data-urlencode "chat_id=$CHAT_ID" \
--data-urlencode "text=$CUERPO" \
--data-urlencode "parse_mode=Markdown" > /dev/null 2>&1
Importante: Dale permisos de ejecución con:
sudo chmod 755 /usr/local/bin/nut-telegram.sh
y haz que el dueño sea el usuario de nut:
sudo chown nut:nut /usr/local/bin/nut-telegram.sh
Configurando los avisos por telegram
Volvemos a configurar las flags para los avisos por telegram, por lo que volvemos a entrar al archivo upsmon.conf
sudo nano /etc/nut/upsmon.conf
Copia encima o debajo de las anteriores notificaciones
# Comando externo para notificaciones
NOTIFYCMD "/usr/local/bin/nut-telegram.sh"
# Definición de mensajes que activan el script
NOTIFYMSG ONLINE "UPS salicru@localhost on line power"
NOTIFYMSG ONBATT "UPS salicru@localhost on battery"
NOTIFYMSG LOWBATT "UPS salicru@localhost low battery"
NOTIFYMSG SHUTDOWN "SHUTDOWN"
NOTIFYMSG REPLBATT "REPLBATT"
Reinicia el servicio
sudo systemctl restart nut-monitor
Haz una prueba manual con:
sudo -u nut /usr/local/bin/nut-telegram.sh "Prueba manual"
Test
Podemos listar los comandos que puede realizar nuestro salicru.
nut@zero:~ $ upscmd -l salicru
Instant commands supported on UPS [salicru]:
beeper.toggle - Toggle the UPS beeper
driver.killpower - Tell the driver daemon to initiate UPS shutdown; should be unlocked with driver.flag.allow_killpower option or variable setting
driver.reload - Reload running driver configuration from the file system (only works for changes in some options)
driver.reload-or-error - Reload running driver configuration from the file system (only works for changes in some options); return an error if something changed and could not be applied live (so the caller can restart it with new options)
driver.reload-or-exit - Reload running driver configuration from the file system (only works for changes in some options); exit the running driver if something changed and could not be applied live (so service management framework can restart it with new options)
load.off - Turn off the load immediately
load.on - Turn on the load immediately
shutdown.return - Turn off the load and return when power is back
shutdown.stayoff - Turn off the load and remain off
shutdown.stop - Stop a shutdown in progress
test.battery.start - Start a battery test
test.battery.start.deep - Start a deep battery test
test.battery.start.quick - Start a quick battery test
test.battery.stop - Stop the battery test
De la lista podemos ejecutar test.battery.start.quick que lo único que hace es pasar al estado OL CAL y hacer un test del sistema para el chequeo interno del SAI pero no hará como su nombre indica, ningún test de las baterías.
nut@zero:~ $ upscmd -u upsmon -p tu_contresña_segura salicru test.battery.start.quick
OK
Mientras se realiza el test, puedes comprobar el voltage de la batería en tiempo real con este comando, que se mantendrá inmutable ya que el el sistema se mantiene todo el tiempo OnLine.
while true; do upsc salicru@localhost battery.voltage; sleep 1; done
Mantenimiento Preventivo Mensual
«Investigando a fondo con la consola de NUT, descubrimos que el Salicru SOHO+ protege sus baterías. Aunque veas comandos como test.battery.start.deep, el SAI los ignora para evitar descargas innecesarias. El único comando que acepta es el quick, que activa el modo OL CAL (Calibración Online). Este modo es genial para verificar que los relés y el inversor funcionan, pero no estresa la batería.
Conclusión: Para saber la salud real de tus baterías en este modelo, el ‘Test del Tirón’ (desenchufar 10 segundos) sigue siendo el único modo. Mi script de Telegram te avisará al instante de cuánto cae el voltaje en ese momento y en que estado se encuentran las baterías.»
Si el driver nutdrv_qx solo nos permite el OL CAL, vamos a convertir ese «estiramiento» en nuestro test mensual. Aunque no descargue la batería, es vital porque obliga a los relés físicos a moverse. Un SAI que nunca hace un test puede acabar con los relés «pegados» por el calor y el desuso, y el día que se vaya la luz de verdad, no conmutará.
Script de «Mantenimiento Preventivo de Relés e Inversor».
Abre una terminal y ejecuta el siguiente comando para crear nuestro archivo de mantenimiento
sudo nano /usr/local/bin/mantenimiento-sai.sh
Pega el siguente texto, no olvides de introducir «tu_token_de_telegram» «tu_id_de_chat» y «tu_contraseña_segura»
#!/bin/bash
# --- CONFIGURACIÓN ---
TOKEN="TU_TOKEN_DE_TELEGRAM"
ID="TU_ID_DE_CHAT"
UPS="salicru"
USUARIO="upsmon"
CLAVE="tu_contraseña_segura"
# 1. Inicio del mantenimiento
curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" -d "chat_id=$ID&text=⚙️ *Mantenimiento Mensual:* Iniciando test de relés en $UPS..."
# 2. Lanzar el Quick Test (Modo CAL)
upscmd -u $USUARIO -p $CLAVE $UPS test.battery.start.quick > /dev/null
sleep 2
# 3. Verificamos si el SAI ha entrado en modo calibración
STATUS=$(upsc $UPS ups.status)
if [[ "$STATUS" == *"CAL"* ]]; then
# Esperamos a que termine (vimos que dura unos 9-10 seg)
sleep 10
FINAL_STATUS=$(upsc $UPS ups.status)
if [[ "$FINAL_STATUS" == "OL" ]]; then
MSG="✅ *TEST OK*: Los relés han conmutado y el inversor ha arrancado correctamente. El sistema de emergencia está operativo."
else
MSG="⚠️ *AVISO*: El test ha terminado pero el estado es $FINAL_STATUS. Revisar manualmente."
fi
else
MSG="❌ *ERROR*: El SAI ha ignorado la orden de test. Es posible que necesite un reinicio del servicio NUT."
fi
# 4. Enviar resultado
curl -s -X POST "https://api.telegram.org/bot$TOKEN/sendMessage" -d "chat_id=$ID&parse_mode=Markdown&text=$MSG"
Este script hará el test aceptado por el Salicru, verificará que el estado pase por OL CAL y te informará de que la electrónica de conmutación sigue viva.
La automatización (Cron)
Para que se haga solo una vez al mes (por ejemplo, el día 1 a las 10:00), añade esto a tu sudo crontab -e:
00 10 1 * * /usr/local/bin/mantenimiento-sai.sh
«¿Por qué automatizar un test que no descarga la batería?»
Muchos usuarios cometen el error de no tocar su SAI hasta que se va la luz. El problema es que los relés son piezas mecánicas que pueden fallar por falta de uso. Mi script mensual fuerza al Salicru a entrar en modo OL CAL. Aunque no descargue la batería, este proceso hace que los relés ‘hagan ejercicio’ y que el inversor se autochequee. Es la garantía de que, cuando llegue el apagón real, la parte mecánica del SAI no estará agarrotada.
Tabla de Salud de la Batería (Sistema de 24V)
«Una vez que recibas la notificación en tu móvil, ¿cómo saber si esos voltios son buenos o malos? He preparado esta tabla de referencia para que sepas cuándo es el momento de sacar la cartera y comprar repuestos:»
| Voltaje en Batería | Estado de Salud | Significado Técnico | Acción |
| > 27.0 V | ✨ Excelente | Carga completa en flotación. | Ninguna. |
| 24.5 V – 26.5 V | ✅ Normal | Funcionamiento correcto bajo carga. | Uso habitual. |
| 23.5 V – 24.4 V | ⚠️ Aviso / Débil | La batería empieza a perder capacidad química. | Planificar cambio a medio plazo. |
| < 23.5 V | 🚨 Crítico | Agotamiento inminente o celdas dañadas. | Cambio urgente. Riesgo de apagón repentino. |