1. Introducción

WIS2 Downloader descarga automáticamente datos desde las memorias caché globales WIS2 (WMO Information System 2.0) en función de sus suscripciones. Usted crea suscripciones para especificar qué temas de datos le interesan, y el sistema gestiona la descarga y organización de los archivos.

Las suscripciones pueden crearse a través de la interfaz web del navegador (recomendado) o directamente mediante la API REST.

2. Interfaz web

La interfaz web está disponible en http://<host>:8080 (de forma predeterminada http://localhost:8080 cuando se ejecuta localmente). El host y el puerto reales dependen de cómo esté desplegado el sistema — consulte con su administrador si accede a una instancia compartida.

Proporciona una forma visual de descubrir los conjuntos de datos WIS2 disponibles, explorar la jerarquía de temas y crear suscripciones sin usar directamente la API REST.

2.1. Idioma de la interfaz

El selector de idioma en la esquina superior derecha del encabezado cambia el idioma de la interfaz. El idioma seleccionado se recuerda para su sesión de navegador.

Idiomas compatibles:

Idioma Dirección del script

English

Izquierda a derecha

Français (French)

Izquierda a derecha

Español (Spanish)

Izquierda a derecha

العربية (Arabic)

Derecha a izquierda

中文 (Chinese)

Izquierda a derecha

Русский (Russian)

Izquierda a derecha

Las traducciones de la interfaz son generadas automáticamente. Si nota una traducción inexacta, especialmente en términos WMO/meteorológicos, infórmelo a través del rastreador de problemas del proyecto.

2.2. Navegación

El cajón de navegación a la izquierda (a la derecha en modo RTL árabe) da acceso a seis vistas. Cada una también es accesible mediante un atajo de teclado:

Atajo Vista Descripción

kbd:[Alt+1]

Panel de control

Paneles integrados que muestran tasas de descarga, profundidad de cola y totales de bytes en tiempo real

kbd:[Alt+2]

Vista de catálogo

Búsqueda de texto completo en los tres catálogos de descubrimiento globales (GDC) con filtrado por política de datos, palabras clave y bounding box

kbd:[Alt+3]

Vista de árbol

Explore la jerarquía completa de temas WIS2 como un árbol navegable y seleccione un tema para abrir el panel lateral de suscripción

kbd:[Alt+4]

Suscripción manual

Introduzca un tema, directorio de guardado y filtro directamente sin explorar el catálogo

kbd:[Alt+5]

Gestionar suscripciones

Lista todas las suscripciones activas y permite cancelar la suscripción a temas

kbd:[Alt+6]

Configuración

Ver recuentos de registros GDC por catálogo y activar una actualización manual de datos

La vista de catálogo consulta registros obtenidos de los tres catálogos de descubrimiento globales WIS2 (CMA, DWD, ECCC), fusionados en una única lista deduplicada.

2.3.1. Filtros de búsqueda

Filtro Descripción

Texto de búsqueda

Coincide con ID de conjunto de datos, título, descripción, versión, palabras clave y conceptos temáticos

Política de datos

all (predeterminado), core o recommended — basado en la Política de Datos Unificada de WMO

Palabras clave

Lista separada por comas; todas las palabras clave deben aparecer en el registro

Bounding box

Grados decimales Norte/Oeste/Este/Sur; devuelve registros cuya geometría intersecte el cuadro

Haga clic en Filtrar para ejecutar la búsqueda. Los resultados están paginados de diez en diez.

2.3.2. Tarjetas de resultados

Cada tarjeta de resultado muestra:

  • Título del conjunto de datos e ID del registro

  • Insignia de política de datos (core = verde, recommended = rojo)

  • Chips de catálogo fuente (CMA = azul, DWD = verde azulado, ECCC = naranja)

  • Un icono de advertencia si el contenido del registro difiere entre catálogos

  • Mostrar metadatos — abre un diálogo con los detalles completos del registro y un mapa interactivo del alcance geográfico del conjunto de datos

  • Seleccionar / Deseleccionar — agrega o elimina el tema MQTT del conjunto de datos en el panel lateral de suscripción

2.4. Vista de árbol

La vista de árbol muestra la jerarquía completa de temas WIS2 derivada de todos los registros GDC cargados. Expanda los nodos para navegar hasta los temas individuales. Escriba en el cuadro de filtro en la parte superior para buscar entre todas las etiquetas de nodos. Haga clic en un nodo hoja para abrir el panel lateral de suscripción.

Solo un tema puede estar activo a la vez en la vista de árbol.

2.5. Crear una suscripción desde la interfaz

Cuando se selecciona un tema (desde la vista de catálogo o la vista de árbol), el panel lateral de suscripción se abre a la derecha.

Campo Descripción

Temas seleccionados

El/los tema(s) MQTT activo(s)

Directorio de guardado

Ruta bajo /data donde se guardarán los archivos (predeterminado ./)

Conjuntos de datos

Filtrar descargas a conjuntos de datos específicos; bloqueado al registro seleccionado en la vista de catálogo

Tipos de medios

Restringir descargas por tipo MIME

Bounding box

Filtro espacial aplicado en el momento de la descarga

Rango de fecha y hora

Filtro temporal aplicado en el momento de la descarga

Filtros personalizados

Campos de filtro específicos del conjunto de datos de los metadatos de enlace del registro GDC (solo vista de catálogo)

Haga clic en Suscribirse para abrir un diálogo de confirmación que muestra la carga útil JSON completa. Revísela y luego haga clic en Confirmar para crear la suscripción, o en Cancelar para volver.

2.6. Gestión de suscripciones

La vista Suscripciones lista todas las suscripciones activas con sus rutas de guardado. Haga clic en Cancelar suscripción en cualquier entrada para eliminarla. Use Recargar suscripciones para actualizar la lista tras cualquier cambio realizado mediante la API.

2.7. Configuración

La vista Configuración muestra cuántos registros se cargaron desde cada GDC. Haga clic en Actualizar datos GDC para forzar una obtención nueva desde los tres catálogos, omitiendo la caché de Redis.

3. Entender los temas WIS2

WIS2 usa jerarquías de temas MQTT para organizar los datos. Los temas siguen este patrón:

origin/a/wis2/{centre-id}/data/{data-policy}/{earth-system-domain}/{category}/...
cache/a/wis2/{centre-id}/data/{data-policy}/{earth-system-domain}/{category}/...
  • origin - Datos originales del proveedor de datos

  • cache - Copia en caché de un caché global (recomendado por fiabilidad)

  • {centre-id} - Código de país/organización, precedido del código de país ISO2C

  • {data-policy} - Política de datos unificada WMO aplicable a los datos (core o recommended)

  • {earth-system-domain} - Dominio del sistema terrestre o disciplina de la política de datos unificada WMO

3.1. Ejemplos de temas

Tema Descripción

cache/a/wis2/de-dwd/data/#

Todos los datos del Deutscher Wetterdienst

cache/a/wis2/+/data/core/weather/surface-based-observations/#

Observaciones de superficie básicas de todos los nodos WIS2

3.2. Comodines

Comodín Significado

+

Coincide exactamente con un nivel (ej.: cualquier código de país)

#

Coincide con cero o más niveles (debe estar al final del tema)

4. Gestión de suscripciones mediante la API REST

Las suscripciones también pueden gestionarse mediante programación usando la API REST. La dirección predeterminada es http://localhost:5002, pero el host y el puerto reales pueden variar según el despliegue.

Use la interfaz Swagger en http://<host>:5002/swagger para la exploración interactiva de la API.

4.1. Crear una suscripción

curl -X POST http://localhost:5002/subscriptions \
  -H "Content-Type: application/json" \
  -d '{
    "topic": "cache/a/wis2/+/data/core/weather/surface-based-observations/#",
    "target": "surface-obs"
  }'

Respuesta:

{
  "status": "accepted",
  "topic": "cache/a/wis2/+/data/core/weather/surface-based-observations/#",
  "target": "surface-obs"
}

4.2. Parámetros de suscripción

Parámetro Requerido Descripción

topic

Patrón de tema MQTT WIS2 con comodines

target

No

Subdirectorio para archivos descargados (bajo /data)

filter

No

Configuración del filtro (ver Filtrado)

4.3. Listar suscripciones

curl http://localhost:5002/subscriptions

Respuesta:

{
  "cache/a/wis2/+/data/core/weather/surface-based-observations/#": {
    "a1b2c3d4-...": {
      "save_path": "surface-obs",
      "filter": {}
    }
  }
}

4.4. Obtener detalles de una suscripción

Primero liste las suscripciones para encontrar el ID de suscripción (a1b2c3d4-…​), luego consúltela por ID:

curl http://localhost:5002/subscriptions/<id>

Respuesta:

{
  "id": "a1b2c3d4-...",
  "topic": "cache/a/wis2/+/data/core/weather/surface-based-observations/#",
  "save_path": "surface-obs",
  "filter": {}
}

4.5. Eliminar una suscripción

curl -X DELETE http://localhost:5002/subscriptions/<id>
Donde <id> es el UUID de suscripción obtenido de GET /subscriptions. Si esta es la última suscripción para el tema, la conexión MQTT también se cierra.

5. Filtrado

Las suscripciones aceptan un objeto filter opcional que controla qué notificaciones se descargan. Los filtros usan reglas ordenadas — la primera regla que coincida determina el resultado.

5.1. Estructura del filtro

{
  "filter": {
    "name": "my-filter",
    "rules": [
      {
        "id": "rule-1",
        "order": 1,
        "match": { ... },
        "action": "accept"
      },
      {
        "id": "default",
        "order": 999,
        "match": { "always": true },
        "action": "reject"
      }
    ]
  }
}

Cada regla requiere:

Campo Requerido Descripción

id

Etiqueta corta mostrada en los registros cuando la regla se activa

order

Las reglas se evalúan en orden ascendente — los números más bajos primero

match

Condición que debe ser verdadera para que se aplique la regla (ver Condiciones de coincidencia)

action

accept, reject o continue (continuar a la siguiente regla)

reason

No

Explicación legible mostrada en registros y métricas

Si ninguna regla coincide, el resultado predeterminado es accept.

5.2. Comportamiento predeterminado (sin filtro)

Cuando no se proporciona ningún filter, se ejecuta un filtro predeterminado integrado que rechaza cualquier tipo de medio que no esté en una lista de permitidos estándar (BUFR, GRIB, NetCDF, HDF5, imágenes comunes y formatos de texto). Para aceptar todo, use un filtro explícito que acepte todo:

{
  "filter": {
    "name": "accept-all",
    "rules": [
      {"id": "accept-all", "order": 1, "match": {"always": true}, "action": "accept"}
    ]
  }
}

5.3. Condiciones de coincidencia

5.3.1. Siempre / Nunca

{"always": true}   (1)
{"always": false}  (2)
1 Coincide incondicionalmente — útil como regla predeterminada al final de una lista
2 Nunca coincide

5.3.2. Campos simples

Coinciden contra los metadatos disponibles en la notificación WIS2:

{"centre_id":   {"equals": "de-dwd"}}
{"topic":       {"pattern": "cache/a/wis2/+/data/core/weather/#"}}
{"href":        {"regex": "\\.bufr4?$"}}
{"data_id":     {"not_equals": "some-id"}}

Campos disponibles:

Campo Descripción

centre_id

Identificador del centro desde la posición 3 del tema (ej.: de-dwd, ca-eccc-msc)

topic

Cadena de tema MQTT completa

href

URL de descarga desde la notificación

data_id

properties.data_id desde la notificación WIS2

metadata_id

properties.metadata_id desde la notificación WIS2

media_type

Tipo MIME detectado del archivo descargado — solo después de la descarga (ver Evaluación antes y después de la descarga)

Operadores disponibles: equals, not_equals, in, not_in, pattern (glob), regex, exists

5.3.3. Tamaño

Coincide con el tamaño del archivo en bytes. El campo size usa sus propios operadores de unidades en bytes:

{"size": {"gt_bytes":  104857600}}             (1)
{"size": {"lte_bytes": 1048576}}               (2)
{"size": {"between_bytes": [1024, 5242880]}}   (3)
1 Mayor que 100 MB
2 1 MB o menos
3 Entre 1 KB y 5 MB

Operadores: gt_bytes, gte_bytes, lt_bytes, lte_bytes, between_bytes, exists

size es el recuento real de bytes descargados y solo se conoce después de que el archivo se haya obtenido — ver Evaluación antes y después de la descarga.

5.3.4. Bounding box geográfico

Coincide si la geometría de la notificación cae dentro del cuadro. Las notificaciones sin geometría se dejan pasar.

{"bbox": {"north": 55.0, "south": 47.0, "east": 15.0, "west": 6.0}}

Las cuatro coordenadas son obligatorias y están en grados decimales.

5.3.5. Propiedades dinámicas de la notificación

Coincide con cualquier campo dentro del objeto properties de la notificación WIS2 usando la clave property:

{"property": "model_run",     "type": "string",   "equals": "00"}
{"property": "forecast_hour", "type": "integer",  "lte": 48}
{"property": "datetime",      "type": "datetime", "gte": "2024-01-01T00:00:00Z"}

Tipos compatibles: string, integer, number, boolean, datetime

5.4. Combinadores

Las condiciones pueden anidarse usando combinadores lógicos:

{"all": [condition1, condition2]}   (1)
{"any": [condition1, condition2]}   (2)
{"not": condition}                  (3)
1 Y — todas las subcondiciones deben coincidir
2 O — cualquier subcondición debe coincidir
3 NO — la subcondición no debe coincidir

Ejemplo — aceptar solo ejecuciones 00Z y 12Z con pronósticos de corto alcance de un centro específico:

{
  "all": [
    {"centre_id": {"equals": "ca-eccc-msc"}},
    {"any": [
      {"property": "model_run", "type": "string", "equals": "00"},
      {"property": "model_run", "type": "string", "equals": "12"}
    ]},
    {"property": "forecast_hour", "type": "integer", "lte": 48}
  ]
}

5.5. Evaluación antes y después de la descarga

media_type y size solo se conocen después de que el archivo ha sido descargado. Los filtros se evalúan dos veces: una antes de la descarga (pre-descarga) y otra después (post-descarga). Las reglas que dependen de media_type o size se omiten silenciosamente en la pasada pre-descarga.

Esto significa que el siguiente filtro rechaza todo — la regla media_type nunca se activa en pre-descarga, y la regla reject-all se activa en su lugar:

{
  "rules": [
    {"id": "accept-bufr", "order": 1,
     "match": {"media_type": {"in": ["application/bufr"]}}, "action": "accept"},
    {"id": "reject-all",  "order": 99,
     "match": {"always": true}, "action": "reject"}
  ]
}

El patrón correcto es proteger la regla de rechazo con media_type.exists, de modo que solo se active en post-descarga cuando el tipo es realmente conocido:

{
  "rules": [
    {"id": "accept-bufr", "order": 1,
     "match": {"media_type": {"in": ["application/bufr", "application/octet-stream"]}},
     "action": "accept"},
    {"id": "reject-wrong-type", "order": 2,
     "match": {"media_type": {"exists": true}},
     "action": "reject", "reason": "Media type not allowed"}
  ]
}

Pre-descarga: ninguna regla se activa (ambas requieren un media_type conocido) → la descarga procede.
Post-descarga: la regla 1 acepta BUFR/octet-stream; la regla 2 rechaza todo lo demás.

5.6. Tipos de medios compatibles

Tipos aceptados por defecto cuando no se especifica ningún filtro:

Categoría Tipos

Formatos WMO

application/bufr, application/grib

Científico

application/x-hdf, application/x-hdf5, application/x-netcdf, application/x-netcdf4

Imágenes

image/gif, image/jpeg, image/png, image/tiff

Documentos

application/pdf, application/postscript

Texto

text/plain, text/html, text/xml, text/csv, text/tab-separated-values

Binario

application/octet-stream

5.7. Ejemplos de filtros

5.7.1. Aceptar solo BUFR y GRIB

{
  "filter": {
    "name": "wmo-formats-only",
    "rules": [
      {
        "id": "accept-wmo",
        "order": 1,
        "match": {"media_type": {"in": ["application/bufr", "application/grib"]}},
        "action": "accept"
      },
      {
        "id": "reject-other",
        "order": 2,
        "match": {"media_type": {"exists": true}},
        "action": "reject",
        "reason": "Not a WMO format"
      }
    ]
  }
}

5.7.2. Rechazar archivos de más de 100 MB

{
  "filter": {
    "name": "size-limit",
    "rules": [
      {
        "id": "reject-large",
        "order": 1,
        "match": {"size": {"gt_bytes": 104857600}},
        "action": "reject",
        "reason": "Exceeds 100 MB"
      }
    ]
  }
}

5.7.3. Datos de un centro específico, solo corto alcance

{
  "filter": {
    "name": "eccc-short-range",
    "rules": [
      {
        "id": "reject-large",
        "order": 1,
        "match": {"size": {"gt_bytes": 104857600}},
        "action": "reject",
        "reason": "Exceeds 100 MB"
      },
      {
        "id": "accept-short-range",
        "order": 2,
        "match": {
          "all": [
            {"property": "model_run",     "type": "string",  "in": ["00", "12"]},
            {"property": "forecast_hour", "type": "integer", "lte": 48}
          ]
        },
        "action": "accept"
      },
      {
        "id": "default",
        "order": 999,
        "match": {"always": true},
        "action": "reject"
      }
    ]
  }
}

5.7.4. Filtro de área geográfica

{
  "filter": {
    "name": "europe-only",
    "rules": [
      {
        "id": "accept-europe",
        "order": 1,
        "match": {"bbox": {"north": 71.0, "south": 34.0, "east": 40.0, "west": -25.0}},
        "action": "accept"
      },
      {
        "id": "default",
        "order": 999,
        "match": {"always": true},
        "action": "reject",
        "reason": "Outside European bounding box"
      }
    ]
  }
}

6. Archivos descargados

6.1. Organización de archivos

Los archivos se organizan bajo su directorio destino en un subdirectorio YYYY/MM/DD basado en la fecha en que el archivo fue descargado (no el tiempo de observación ni el tiempo de validez de los datos):

/data/
└── surface-obs/           # Your target directory
    └── 2026/
        └── 03/
            └── 05/        # Date downloaded (UTC)
                ├── SYNOP_20260305T120000.bufr
                ├── SYNOP_20260305T121500.bufr
                └── ...
La fecha del directorio refleja cuándo llegó el archivo, no cuándo se produjeron los datos ni para qué período son válidos. Los archivos de períodos de observación más antiguos que lleguen tarde aparecerán en el directorio correspondiente a su fecha de descarga.

6.2. Nomenclatura de archivos

Los archivos conservan sus nombres originales de la URL de descarga. Si ya existe un archivo con el mismo nombre y no es una actualización, la descarga se omite.

6.3. Ver descargas

# Listar descargas recientes
ls -la downloads/surface-obs/$(date +%Y/%m/%d)/

# Contar archivos por tipo
find downloads/ -name "*.bufr" | wc -l

# Tamaño total
du -sh downloads/
du informa el uso de disco basándose en la asignación de bloques del sistema de archivos, no en el recuento de bytes en bruto. Muchos archivos pequeños (como los boletines BUFR) consumen un bloque completo cada uno independientemente de su tamaño real, por lo que los resultados de du serán típicamente mayores que la suma de los tamaños de archivos individuales indicados por ls -la.

7. Monitoreo

7.1. Comprobación de estado

curl http://localhost:5002/health

Respuesta:

{"status": "healthy"}

7.2. Métricas

Ver estadísticas de descarga:

# Total de descargas
curl -s http://localhost:5002/metrics | grep wis2downloader_downloads_total

# Descargas fallidas
curl -s http://localhost:5002/metrics | grep wis2downloader_failed_total

# Profundidad de la cola
curl -s http://localhost:5002/metrics | grep wis2downloader_celery_queue_length

7.3. Vista de panel de control

El panel de control integrado (kbd:[Alt+1]) muestra tasas de descarga, profundidad de cola, uso de disco y totales de bytes en tiempo real. No se requiere inicio de sesión adicional.

El panel de control está integrado directamente en la interfaz web — no es necesario abrir Grafana por separado.

8. Casos de uso comunes

8.1. Suscribirse a todas las observaciones de superficie

curl -X POST http://localhost:5002/subscriptions \
  -H "Content-Type: application/json" \
  -d '{
    "topic": "cache/a/wis2/+/data/core/weather/surface-based-observations/#",
    "target": "synop"
  }'

8.2. Suscribirse a un país específico

curl -X POST http://localhost:5002/subscriptions \
  -H "Content-Type: application/json" \
  -d '{
    "topic": "cache/a/wis2/de-dwd/data/#",
    "target": "dwd"
  }'

8.3. Descargar solo archivos BUFR y GRIB

curl -X POST http://localhost:5002/subscriptions \
  -H "Content-Type: application/json" \
  -d '{
    "topic": "cache/a/wis2/+/data/#",
    "target": "wmo-formats",
    "filter": {
      "name": "wmo-formats-only",
      "rules": [
        {
          "id": "accept-wmo",
          "order": 1,
          "match": {"media_type": {"in": ["application/bufr", "application/grib"]}},
          "action": "accept"
        },
        {
          "id": "reject-other",
          "order": 2,
          "match": {"media_type": {"exists": true}},
          "action": "reject",
          "reason": "Not a WMO format"
        }
      ]
    }
  }'

8.4. Suscripciones múltiples

Cree suscripciones separadas para diferentes tipos de datos:

# Observaciones de superficie
curl -X POST http://localhost:5002/subscriptions \
  -H "Content-Type: application/json" \
  -d '{"topic": "cache/a/wis2/+/data/core/weather/surface-based-observations/#", "target": "surface"}'

# Viento en altura
curl -X POST http://localhost:5002/subscriptions \
  -H "Content-Type: application/json" \
  -d '{"topic": "cache/a/wis2/+/data/core/weather/upper-air-observations/#", "target": "upper-air"}'

# Pronósticos
curl -X POST http://localhost:5002/subscriptions \
  -H "Content-Type: application/json" \
  -d '{"topic": "cache/a/wis2/+/data/core/weather/prediction/#", "target": "forecasts"}'

9. Solución de problemas

9.1. Sin archivos descargados

  1. Verifique que existe la suscripción:

    curl http://localhost:5002/subscriptions
  2. Verifique el estado del sistema:

    curl http://localhost:5002/health
  3. Verifique las descargas omitidas (métricas):

    curl -s http://localhost:5002/metrics | grep skipped

9.2. Archivos siendo omitidos

Compruebe el motivo de omisión en las métricas:

curl -s http://localhost:5002/metrics | grep wis2downloader_skipped_total

Motivos comunes:

  • PreviouslyProcessed - Archivo ya descargado (deduplicación)

  • FilterRejected - Rechazado por una regla de filtro

  • GlobalCacheBlacklisted - Caché excluido mediante GC_EXCLUDE

9.3. Tipos de archivos incorrectos descargados

Elimine la suscripción existente y vuelva a crearla con un filtro media_type. Use media_type.exists como guardia de rechazo — no always: true — para que la regla de rechazo solo se active después de que se conozca el tipo de archivo (ver Evaluación antes y después de la descarga):

# Listar suscripciones para encontrar el UUID
curl http://localhost:5002/subscriptions

# Eliminar suscripción antigua por UUID
curl -X DELETE http://localhost:5002/subscriptions/<id>

# Crear nueva suscripción con filtro
curl -X POST http://localhost:5002/subscriptions \
  -H "Content-Type: application/json" \
  -d '{
    "topic": "your-topic",
    "target": "your-target",
    "filter": {
      "name": "bufr-only",
      "rules": [
        {
          "id": "accept-bufr",
          "order": 1,
          "match": {"media_type": {"in": ["application/bufr", "application/octet-stream"]}},
          "action": "accept"
        },
        {
          "id": "reject-other",
          "order": 2,
          "match": {"media_type": {"exists": true}},
          "action": "reject",
          "reason": "Media type not allowed"
        }
      ]
    }
  }'

9.4. Todo siendo rechazado por el filtro

Si todas las notificaciones son rechazadas con el motivo FilterRejected, la causa más común es una regla de rechazo always: true que se activa en pre-descarga antes de que se conozca media_type.

Compruebe su filtro: si tiene una regla de aceptación media_type seguida de una regla de rechazo always: true, la regla de aceptación nunca se activará en pre-descarga porque media_type solo se conoce después de la descarga. Reemplace el rechazo always: true por media_type.exists: true — ver Evaluación antes y después de la descarga.