Analema
Herramienta web que permite visualizar las trayectorias solares y lunares desde cualquier ubicación geográfica.
Un sistema completo para la captura fotográfica automatizada y visualización interactiva de analemas solares y lunares.
Este proyecto automatiza la captura periódica de imágenes provenientes de webcams públicas, generando secuencias (timelapses) que evidencian el movimiento aparente del Sol y la Luna a lo largo del tiempo. Las imágenes son capturadas en momentos astronómicos precisos mediante GitHub Actions y consumidas luego en un Visualizador Web Moderno (PWA) de alto rendimiento. Todo el sistema funciona sin requerir bases de datos tradicionales, basándose en el propio sistema de archivos de un repositorio Git.
Arquitectura del Software
Para mantener el código mantenible, escalable y testable, el núcleo del orquestador fotográfico (src/) ha sido estructurado siguiendo estrictamente los preceptos de Clean Architecture y Domain-Driven Design (DDD).
1. Domain Layer
Es el corazón del software. Aquí residen las reglas de negocio puras, independientes de cualquier framework o infraestructura externa:
- Entidades (
Location,Camera): UnLocationencapsula datos geográficos (país, estado, ciudad) y genera identificadores dinámicos. UnaCameraestá vinculada a unLocationy mantiene su orientación cardinal. - Value Objects: Objetos como
CelestialObjectestandarizan el vocabulario de dominio. - Contratos (Interfaces): Abstracciones como
ScheduleRepositoryque definen cómo el dominio espera obtener o persistir datos.
2. Application Layer
Contiene los casos de uso principales. Actúa como el orquestador que coordina el Dominio y la Infraestructura para cumplir con los requerimientos del sistema.
Scheduler: Es el encargado de revisar los horarios programados de cadaLocation. Si la hora actual de ejecución coincide (o se encuentra en el umbral) de una captura programada, coordina al servicio de captura correspondiente para obtener la imagen.
3. Infrastructure Layer
Donde el código interactúa con servicios externos, I/O, y frameworks:
- Servicios de Captura: Se utiliza Puppeteer (
PuppeteerCaptureService) para visitar páginas web de webcams públicas, esperar la carga de componentes multimedia y extraer limpiamente los fotogramas (screenshots) del flujo de video o canvas sin incluir la interfaz web. ConfigScheduleRepository: Un repositorio dinámico que usa configuraciones para calcular horarios precisos de captura en las coordenadas de cadaLocationregistradas ensrc/config/locations.ts.
Ciclo de Orquestación
El orquestador está diseñado para ejecutarse cíclicamente a través de GitHub Actions, optimizando recursos mediante un cronjob.
sequenceDiagram
participant GH as GitHub Actions (Cron)
participant App as Scheduler
participant Repo as ConfigScheduleRepository
participant Cam as PuppeteerCaptureService
participant FS as File System / Git
GH->>App: Ejecuta ciclo horario (minuto 0)
App->>Repo: Consulta horas de captura para el día
Repo-->>App: Retorna { sun: '12:05', moon: '03:45' }
App->>App: Evalúa si la hora del sistema (America/La_Paz) coincide
alt Coincide con evento Solar en el umbral
App->>Cam: Lanza Puppeteer Headless
Cam-->>App: Extrae y retorna buffer de imagen (Screenshot)
App->>FS: Guarda archivo en 'captures/sun/{location}/{camera}/{YYYY-MM-DD}.jpg'
GH->>FS: Realiza Git Commit y Push al repositorio
end
Configuración y Variables de Entorno
El sistema se basa en configuraciones centralizadas, requiriendo muy poco para ejecutarse. Lo principal es la sincronización temporal.
| Variable | Descripción |
|---|---|
TZ | Crítico: Asegura la configuración de la zona horaria en America/La_Paz (UTC-4). La aplicación utiliza este ancla para sincronizar y comparar los horarios astronómicos esperados con el cronjob horario. |
Web Viewer
Esta es una aplicación web interactiva diseñada específicamente para visualizar fluidamente decenas de miles de capturas fotográficas (timelapses) generadas por el orquestador principal del proyecto, evidenciando los trayectos del Sol y la Luna a lo largo de extensos períodos de tiempo.
Arquitectura UI y Experiencia de Usuario (UX)
La aplicación web ha sido concebida para brindar un rendimiento superior, especialmente al manipular un gran volumen de imágenes a alta resolución sin comprometer la memoria o fluidez del navegador.
Transiciones Fluidas
Se implementa una navegación que intercepta los clics del usuario y carga dinámicamente la siguiente página en el DOM sin recargar la pantalla completa. Esto asegura que el estado de la interfaz, como el tema visual o la navegación principal, se mantenga ininterrumpido.
Persistencia del Modo Oscuro
El esquema de color oscuro/claro es detectado desde el sistema y mantenido consistentemente a lo largo de las sesiones del usuario. Gracias a la sincronización con las transiciones de página, no existen parpadeos visuales (“flickering”) al navegar entre diferentes vistas.
El Corazón del Visor: El Reproductor
Un reto crítico al visualizar miles de imágenes (ej. un Analema anual tiene 365 cuadros de alta resolución) es el colapso de la memoria del dispositivo del usuario final. Para mitigarlo, el reproductor de imágenes se apoya en una arquitectura liviana y optimizada:
stateDiagram-v2
[*] --> Initialization: Carga dataset URLs
Initialization --> BufferedLoading: Pre-carga primera imagen (Preview)
BufferedLoading --> BackgroundLoading: Carga progresiva de lotes
BackgroundLoading --> Ready: Se alcanza el umbral mínimo (ej. 20%)
Ready --> Playback: Usuario inicia reproducción
Playback --> Tick: Actualiza imagen basado en FPS
Tick --> UpdateFrame: Renderiza siguiente cuadro
UpdateFrame --> Playback: Bucle si hay más cuadros
1. Carga Bufferizada Asíncrona (Buffered Loading)
En lugar de forzar al navegador a descargar todas las imágenes antes de permitir la interacción, el reproductor inicia un proceso en segundo plano que descarga las imágenes en pequeños lotes asíncronos. La reproducción se habilita una vez que un porcentaje mínimo de cuadros ya está disponible localmente, previniendo bloqueos visuales.
2. Control Dinámico de Velocidad
El usuario tiene control total sobre la velocidad de reproducción, que puede ser ajustada en tiempo real. El reproductor recalcula instantáneamente los intervalos de transición entre cuadros (FPS) sin interrupciones.
Indexación sin Bases de Datos Relacionales
Todo el sistema está diseñado para prescindir de infraestructuras complejas como bases de datos SQL o NoSQL.
En su lugar, el visor web indexa directamente la estructura de carpetas estáticas donde residen las imágenes (captures/) durante el proceso de compilación:
graph LR
A["Proceso de Construcción"] -->|Lectura del sistema de archivos| B(Directorio estático 'captures/')
B --> C{Parsea la estructura jerárquica}
C -->|Clasificación por ubicación y cámara| D[Agrupa secuencias fotográficas]
D --> E[Genera índice de metadatos JSON]
E -.->|Alimenta las vistas web| F(Renderizado y Filtros UI)
Este índice ligero es consumido por la interfaz web, permitiendo aplicar filtros rápidos y precisos en el lado del cliente sin requerir peticiones de red adicionales ni latencia.
Listo para Dispositivos Móviles y Offline
El visor web incorpora características avanzadas para maximizar su alcance:
- Metadatos Optimizados para asegurar que los enlaces compartidos en redes sociales incluyan imágenes y descripciones representativas.
- Configurado como Aplicación Web Progresiva (PWA), permitiendo su instalación directa en dispositivos.
- Modo Offline Básico, implementando políticas de caché mediante un Service Worker para ofrecer una experiencia continua incluso con redes inestables.
- Tipografías Auto-alojadas, evitando tiempos de carga adicionales o dependencias de servidores externos.