Monitor autonomo y portable de camaras LAN con Python, systemd y WhatsApp Cloud API
  • Python 97.7%
  • Shell 2.3%
Find a file
2026-08-31 16:41:24 -05:00
docs feat: añade alert script de prueba para Zabbix 2026-08-20 14:22:04 -05:00
zabbix_alertscripts feat: prepara plantilla utility para alertas de Zabbix 2026-08-31 16:41:24 -05:00
.env.example feat: implementa monitor autonomo de camaras LAN 2026-08-17 14:03:35 -05:00
.gitignore feat: implementa monitor autonomo de camaras LAN 2026-08-17 14:03:35 -05:00
camera-monitor.service feat: implementa monitor autonomo de camaras LAN 2026-08-17 14:03:35 -05:00
camera_monitor.py feat: notifica recuperaciones por host 2026-08-20 12:24:37 -05:00
install_ubuntu.sh feat: implementa monitor autonomo de camaras LAN 2026-08-17 14:03:35 -05:00
produccion-y-costos-de-whatsapp.md docs: aclara costos y limites de WhatsApp 2026-08-17 15:27:51 -05:00
README.md feat: prepara plantilla utility para alertas de Zabbix 2026-08-31 16:41:24 -05:00
requirements.txt feat: implementa monitor autonomo de camaras LAN 2026-08-17 14:03:35 -05:00
set_whatsapp_token.py feat: implementa monitor autonomo de camaras LAN 2026-08-17 14:03:35 -05:00
test_camera_monitor.py feat: notifica recuperaciones por host 2026-08-20 12:24:37 -05:00
test_zabbix_alertscript.py feat: prepara plantilla utility para alertas de Zabbix 2026-08-31 16:41:24 -05:00

Monitor autónomo de cámaras LAN

Prueba de concepto en Python para detectar caídas y recuperaciones de cámaras IP y avisar mediante la API oficial de WhatsApp Cloud. Está pensada para Ubuntu, no abre puertos, no necesita privilegios de root y usa únicamente la biblioteca estándar de Python.

Estado: PoC validada localmente. El servicio permanente y la integración de WhatsApp para producción todavía no están activados.

Documentos destacados

Qué resuelve

  • Comprueba cualquier cantidad de cámaras mediante ICMP, TCP o ambos.
  • Evita declarar una caída por un fallo aislado.
  • Mantiene estados independientes UNKNOWN, UP y DOWN.
  • Confirma recuperaciones con varias rondas correctas.
  • Limita la cantidad de comprobaciones simultáneas.
  • Conserva el estado después de reiniciar y evita alertas duplicadas.
  • Detecta opcionalmente una posible caída general del gateway.
  • Mantiene una cola de notificaciones cuando Meta o Internet no responden.
  • Rota los registros y nunca escribe el token en ellos.
  • Incluye una unidad endurecida de systemd y un instalador para Ubuntu.

Cómo funciona

Cámaras LAN ──► ping/TCP concurrente ──► máquina de estados
                                               │
Gateway opcional ──► detección de caída general│
                                               ▼
                                      cola persistente
                                               │
                                               ▼
                                     WhatsApp Cloud API

Para integrar Zabbix sin enviar mensajes reales durante la validación, el repositorio incluye zabbix_alertscripts/camera_whatsapp_dryrun.py. El script recibe los datos de una alerta, los registra localmente en formato JSON y no realiza conexiones de red. Se instalará como alert script de Zabbix antes de crear el medio y la acción exclusivos para cámaras.

Para una validación temporal con WhatsApp Cloud API real existe además zabbix_alertscripts/camera_whatsapp_test.py. Lee sus valores únicamente de /etc/zabbix/camera-whatsapp-test.env en el CT de Zabbix y envía texto libre. Debe usarse solo mientras el destinatario haya abierto una ventana de atención; las alertas autónomas fuera de esa ventana requieren una plantilla utility.

El canal preparado para producción es zabbix_alertscripts/camera_whatsapp_template.py. Usa la plantilla utility camera_status_alert con cuatro parámetros: estado, cámara, hora y referencia del evento. No se activa ni se instala con credenciales: cuando exista un número propio, se crea /etc/zabbix/camera-whatsapp.env con los datos reales, se instala el script como medio Script de Zabbix y se cambia la acción desde dry-run de manera controlada.

Una ronda fallida no equivale inmediatamente a una caída. Cada cámara pasa a DOWN después de FAILURE_ROUNDS_BEFORE_DOWN rondas completas fallidas. Una cámara caída vuelve a UP sólo después de SUCCESS_ROUNDS_BEFORE_RECOVERY rondas correctas consecutivas.

Cuando se detecta una caída común de red, se genera un único aviso de infraestructura para evitar una tormenta de mensajes. En cambio, las recuperaciones siempre se notifican por host: cada cámara emite su propio evento RECOVERY una vez que confirma su vuelta a UP; no se envía un mensaje genérico de recuperación de red que oculte qué cámaras volvieron.

Estado de la demostración

La prueba realizada el 17 de agosto de 2026 usó:

  • Ubuntu 26.04 LTS, Python 3.14.4 y systemd 259.
  • Cámara De los Picaflores Oeste, 192.168.100.63, RTSP/TCP 554.
  • Modo ping_and_tcp; no se copiaron credenciales ni rutas RTSP.
  • Tres rondas fallidas y una única transición UNKNOWN → DOWN.
  • Un hello_world aceptado por Meta.
  • Un texto libre de prueba aceptado dentro de la ventana de servicio y confirmado como recibido por el usuario.
  • 24 pruebas automatizadas, sin tráfico real hacia cámaras ni Meta.

El detalle y las limitaciones de esa validación están en docs/validacion-poc.md.

Requisitos

  • Linux con ping compatible con iputils.
  • Python 3.11 o posterior recomendado.
  • Acceso de red desde el equipo monitor hacia las cámaras.
  • systemd sólo si se desea instalar el servicio permanente.
  • Sin paquetes de Python externos.

Inicio rápido

git clone https://forge.custronix.com/custronix/camera-monitor-poc.git
cd camera-monitor-poc
cp .env.example .env
chmod 600 .env
python3 camera_monitor.py --check-config
python3 -m unittest -v
python3 camera_monitor.py --once --dry-run
python3 camera_monitor.py --show-status

--dry-run ejecuta la lógica completa y conserva las notificaciones pendientes, pero nunca llama a Meta.

Configurar cámaras

Edite únicamente el bloque CONFIGURACIÓN EDITABLE al principio de camera_monitor.py:

CAMERAS = [
    {
        "name": "Entrada",
        "host": "192.168.100.101",
        "enabled": True,
        "check_mode": "ping_and_tcp",
        "port": 554,
    },
    {
        "name": "Patio",
        "host": "192.168.100.102",
        "enabled": False,
        "check_mode": "tcp",
        "port": 554,
    },
]

Modos disponibles:

Modo Condición para considerar la cámara disponible
ping Responde ICMP.
tcp Acepta una conexión al puerto configurado.
ping_and_tcp Responde ICMP y acepta TCP.
ping_or_tcp Responde al menos uno de los dos métodos.

No se necesitan credenciales RTSP: la prueba TCP abre una conexión y la cierra inmediatamente. Si una cámara bloquea ICMP, use tcp o ping_or_tcp.

Después de editar:

python3 camera_monitor.py --check-config

El validador identifica nombres duplicados, hosts vacíos o inválidos, puertos fuera de rango, modos desconocidos y parámetros globales inconsistentes.

Parámetros iniciales

Parámetro Valor Efecto
Intervalo normal 30 s Tiempo entre rondas.
Intentos rápidos 3 Intentos dentro de una ronda.
Pausa rápida 5 s Espera entre intentos.
Timeout ICMP/TCP 3 s Límite individual.
Umbral de caída 3 rondas Confirma DOWN.
Umbral de recuperación 2 rondas Confirma UP después de DOWN.
Repetición de alerta DOWN 0 No repite mientras siga caída.
Trabajadores 10 Máximo de cámaras simultáneas.
Cola 100 Máximo de notificaciones pendientes.
Registros 5 × 2 MiB Rotación local.

El gateway 192.168.100.1 está configurado para la demostración, pero su control permanece desactivado. Al replicar el proyecto, cambie GATEWAY_HOST y active GATEWAY_CHECK_ENABLED sólo después de comprobarlo.

Comandos

Comando Función
--check-config Valida sin comprobar cámaras ni enviar mensajes.
--once Ejecuta una ronda y termina.
--show-status Muestra estados y cola pendiente.
--dry-run Impide cualquier envío a Meta.
--test-notification Envía exactamente un hello_world.
--test-text-notification Envía un texto manual para la primera cámara DOWN; sólo funciona dentro de la ventana de servicio.

Configuración de WhatsApp para pruebas

El repositorio incluye .env.example. El archivo real .env está ignorado por Git y debe conservar permisos restrictivos.

cp .env.example .env
chmod 600 .env
python3 set_whatsapp_token.py .env

El helper solicita el token sin eco, lo escribe atómicamente y activa WHATSAPP_ENABLED=true. No pegue tokens en comandos, incidencias, commits o chats.

Para cargar el entorno en una prueba local:

set -a
. ./.env
set +a
python3 camera_monitor.py --test-notification

hello_world no acepta detalles dinámicos. --test-text-notification sirve únicamente para una prueba manual después de que el destinatario haya escrito al número de Meta y abierto la ventana de atención. Ninguna de las dos opciones es la solución automática de producción.

Instalación como servicio Ubuntu

Ejecute esto sólo después de validar cámaras reales en --dry-run:

sudo ./install_ubuntu.sh
sudo /opt/camera-monitor/set_whatsapp_token.py \
  /etc/camera-monitor/camera-monitor.env
sudo -u camera-monitor /usr/bin/python3 \
  /opt/camera-monitor/camera_monitor.py --check-config

El instalador crea:

  • usuario bloqueado camera-monitor;
  • aplicación en /opt/camera-monitor;
  • entorno en /etc/camera-monitor/camera-monitor.env;
  • estado en /var/lib/camera-monitor;
  • registros en /var/log/camera-monitor;
  • unidad /etc/systemd/system/camera-monitor.service.

Deliberadamente no habilita ni inicia el servicio. Valide una ronda como el usuario de servicio antes de activarlo:

sudo -u camera-monitor env \
  CAMERA_MONITOR_STATE_FILE=/var/lib/camera-monitor/camera_state.json \
  CAMERA_MONITOR_LOG_FILE=/var/log/camera-monitor/camera_monitor.log \
  /usr/bin/python3 /opt/camera-monitor/camera_monitor.py --once --dry-run

sudo systemctl enable --now camera-monitor.service
systemctl status camera-monitor.service
journalctl -u camera-monitor.service -f

Producción con WhatsApp

La PoC todavía usa hello_world para alertas automáticas. Antes de producción se necesita un número empresarial, token de usuario de sistema, plantilla utility aprobada con parámetros, método de pago, seguimiento de estados por webhook y controles de gasto y seguridad.

La guía completa, incluidos costos vigentes para Ecuador y el cambio anunciado para octubre de 2026, está en produccion-y-costos-de-whatsapp.md.

Archivos principales

Archivo Propósito
camera_monitor.py Monitor, configuración, CLI y notificaciones.
test_camera_monitor.py Pruebas con cámaras y Meta simulados.
.env.example Plantilla publicable, sin credenciales.
set_whatsapp_token.py Ingreso silencioso y atómico del token.
camera-monitor.service Unidad systemd endurecida.
install_ubuntu.sh Instalación portable sin activación automática.
docs/validacion-poc.md Evidencia y alcance de la prueba local.
produccion-y-costos-de-whatsapp.md Acceso visible a requisitos, costos y plan de producción.
docs/whatsapp-produccion.md Guía técnica completa de producción.

El estado, los registros, .env y __pycache__ están excluidos mediante .gitignore.

Limitaciones actuales

  • El envío automático sigue usando la plantilla estática hello_world.
  • No se reciben webhooks de entrega, lectura o fallo.
  • El servicio systemd está preparado, pero no instalado ni activo.
  • La configuración de cámaras sigue dentro del código.
  • Sólo existe un destinatario de WhatsApp.
  • No hay presupuesto diario, métrica de costo ni panel de salud.
  • Un HTTP 200 de Meta confirma aceptación, no entrega al teléfono.

Estas limitaciones son deliberadas para mantener pequeña y auditable la PoC.