Mareas
-0.13 m en la ultima hora
Valores por hora
| Hora | Prom | ↓ Mín | ↑ Máx |
|---|---|---|---|
| 00:00 | 0.86 m | 0.59 m | 1.15 m |
| 01:00 | 0.80 m | 0.54 m | 1.09 m |
| 02:00 | 0.76 m | 0.50 m | 1.05 m |
| 03:00 | 0.74 m | 0.47 m | 1.03 m |
| 04:00 | 0.78 m | 0.52 m | 1.07 m |
| 05:00 | 0.89 m | 0.63 m | 1.18 m |
| 06:00 | 1.06 m | 0.79 m | 1.35 m |
| 07:00 | 1.26 m | 1.00 m | 1.55 m |
| 08:00 | 1.43 m | 1.17 m | 1.72 m |
| 09:00 | 1.53 m | 1.27 m | 1.82 m |
| 10:00 | 1.53 m | 1.27 m | 1.82 m |
| 11:00 | 1.45 m | 1.19 m | 1.74 m |
| 12:00 | 1.33 m | 1.06 m | 1.62 m |
| 13:00 | 1.20 m | 0.94 m | 1.49 m |
| 14:00 | 1.06 m | 0.80 m | 1.35 m |
| 15:00 | 0.94 m | 0.67 m | 1.23 m |
| 16:00 | 0.83 m | 0.57 m | 1.12 m |
| 17:00 | 0.80 m | 0.53 m | 1.09 m |
| 18:00 | 0.84 m | 0.58 m | 1.13 m |
| 19:00 | 0.95 m | 0.68 m | 1.24 m |
| 20:00 | 1.07 m | 0.81 m | 1.36 m |
| 21:00 | 1.15 m | 0.89 m | 1.44 m |
| 22:00 | 1.16 m | 0.90 m | 1.45 m |
| 23:00 | 1.10 m | 0.84 m | 1.39 m |
| 23:59 | 1.00 m | 0.73 m | 1.29 m |
Arquitectura e implementación
Un pipeline construye el historial de marea y clima en BigQuery. Otro sirve la web en tiempo real.
La ventana de pronóstico local se solapa día a día, así que un append ciego duplicaría filas sin límite. Cada ejecución hace MERGE por estación+fecha+hora: inserta lo nuevo, actualiza lo que cambió, y el historial de marea y clima queda disponible sin duplicados ni costo creciente.
Cuando una fuente externa se atrasa o deja de responder, el pipeline no aborta todo el run: sigue actualizando el resto normalmente y loggea el problema puntual como warning.
BigQuery
mareas_raw.lecturas - MERGE incremental
EN NÚMEROS
- Primera carga: 195 filas (101 San Fernando, 47 Rosario, 47 Zárate)
- Hoy solo San Fernando: Rosario/Zárate se muestran en vivo pero no se cargan a BigQuery
- Cada ejecución actualiza por estación+fecha+hora: nunca duplica
dbt
2 stagings + 1 mart, full outer join
HACE
- stg_mareas_ina / stg_mareas_smn separan por fuente, sin transformar
- mareas_por_estacion cruza marea y clima por estación, fecha y hora
TESTS
- Genéricos: not_null y accepted_values sobre el mart
- assert_san_fernando_pronostico_reciente - error si se atrasa
- assert_staging_sin_duplicados - confirma que el MERGE no dejó duplicados
Airflow
Motor en el repo hermano (imagen sobre apache/airflow:3.3.0); el DAG vive en este repo
HACE
- actualizar_cache → cargar_bigquery → dbt_run → dbt_test, todos los días
- El repo hermano monta este código como volumen: código y credenciales, nada más
- El DAG viaja por script, no por symlink (compatibilidad con Windows)
INA
Instituto Nacional del Agua - REST JSON
alerta.ina.gob.ar/pub/gui/datosProno&calId=432&seriesId=26202
&timeStart=now-1days&timeEnd=now+4days
LA API ENTREGA
- 5 valores de altura posibles por hora
- 4 días, 3 estaciones: San Fernando, Rosario, Zárate
LA APP CALCULA
- Mín, promedio y máx agrupando los 5 valores por hora
- Altura actual por interpolación lineal entre registros
- Próximo máximo y mínimo detectando cambio de pendiente
SMN
Servicio Meteorológico Nacional - ZIP descarga
?dato=pron5d
LA API ENTREGA
- ZIP con un TXT de pronóstico por localidad
- Temperatura, grados de viento, velocidad y precipitación
- Fechas DD/MMM/AAAA, horas como "06Hs."
LA APP HACE
- Descomprime el ZIP y detecta el encoding del TXT
- Extrae el bloque de cada estación con regex
- Convierte fecha a ISO y grados de viento a abreviatura
- Mergea los campos meteorológicos con los datos de marea
App sin base de datos
Lo que ve el usuario corre sobre file-based cache - sin ORM ni migraciones
Tecnologías aplicadas
Views, templates, service layer y management commands. Whitenoise sirve los estáticos.
Carga incremental y modelado en capas, en paralelo, sin afectar la ruta del usuario.
Orquestación diaria en un repo hermano, con imagen propia sobre apache/airflow.
Fetch con urllib, parámetros dinámicos por estación.
Descarga, descompresión y parseo de TXT en Python.
Persistencia por archivo, sin servidor ni base de datos.
El gráfico se construye con código: paths, coordenadas y escalado calculados en JS, sin librería de visualización.
Management commands
Actualización y validación sin depender de la interfaz web.
mareas_actualizar_datos
Obtiene datos frescos de INA y SMN, actualiza el cache.
mareas_validar_fuente
Valida integridad del catálogo y los archivos de cache.
mareas_listar_estaciones
Lista estaciones con estado del cache actual.
mareas_ver_contexto
Muestra el contexto completo renderizado por la vista.
mareas_cargar_bigquery
Sube el cache actual a BigQuery (MERGE incremental). Admite --station para una sola estación; en producción solo corre para san_fernando.
Código fuente completo
El repo público incluye la app, el modelado dbt y el DAG de Airflow completos.