Servidor de dados meteorológicos e de poluição atmosférica com dados reais. Baixa previsões do GFS (NOAA), boletins METAR ao vivo, gera mapas PNG, armazena tudo em SQLite + CSV e serve via API REST (FastAPI) com um dashboard web.
- O que é o Server MET?
- Como o sistema funciona
- Funcionalidades
- Pré-requisitos
- Tutorial passo a passo
- Configuração (.env)
- O pipeline em detalhes
- Entendendo os dados
- Onde os dados ficam armazenados
- A API REST
- O frontend e o dashboard
- Docker (opcional)
- Testes e validação
- Estrutura do projeto
- Solução de problemas
- Dúvidas frequentes (FAQ)
O Server MET é um servidor completo de dados meteorológicos e de poluição do ar. Ele faz sozinho (quase) todo o trabalho:
- Baixa previsões reais do modelo GFS da NOAA (temperatura, umidade, vento, chuva, nuvens, ozônio...) já recortadas por região e variável;
- Busca boletins METAR ao vivo das principais estações brasileiras (condições atuais de aeroportos);
- Processa esses dados em estatísticas (mínimo, máximo, média);
- Gera mapas PNG com a distribuição espacial de cada variável;
- Salva tudo em um banco SQLite (e exporta em CSV);
- Entrega os dados e mapas por meio de uma API REST e um frontend com dashboard.
💡 Em uma frase: digite um comando, e o Server MET baixa previsões do tempo reais, gera mapas do Brasil e deixa tudo pronto para consultar na web ou via API.
Pense no Server MET como uma pequena fábrica de previsões do tempo. Ela trabalha em 4 setores, um depois do outro:
1. Ingestão — os entregadores buscam a matéria-prima.
O pipeline vai até as fontes reais e traz os dados: previsões do modelo GFS da NOAA
(arquivos GRIB, já recortados por região e variável) e boletins METAR ao vivo da
AviationWeather. Os arquivos crus ficam guardados em data/grib/ e data/metar/.
2. Processamento — a cozinha transforma os dados crus.
O core/processor.py lê cada arquivo, recorta a região pedida e calcula o que importa:
o mínimo, o máximo e a média de cada variável.
3. Armazenamento — o almoxarifado organiza tudo.
Os resultados viram registros no banco SQLite, exportações CSV e mapas PNG na
pasta maps/.
4. Exposição — o balcão de atendimento.
O FastAPI serve tudo para o mundo: o frontend com dashboard em http://localhost:8000,
a API REST (base /api/v1) e a documentação interativa em /docs.
Em uma linha, o caminho dos dados é:
NOAA GFS -> downloader -> processor -> SQLite / CSV / Mapas -> FastAPI -> Frontend
AviationWeather -> metar -> SQLite -> FastAPI -> Frontend
A tabela abaixo resume cada etapa:
| Etapa | O que acontece | Onde |
|---|---|---|
| ① Ingestão | O downloader pede à NOAA apenas a variável, o nível e a região que você quer (arquivos GRIB pequenos, ~1 MB). Em paralelo, o metar consulta os boletins ao vivo. |
core/downloader.py, core/metar.py |
| ② Processamento | O processor lê cada GRIB, recorta a região, calcula mínimo/máximo/média e monta a matriz de valores. |
core/grib_reader.py, core/processor.py |
| ③ Armazenamento | A persistence grava os resultados no SQLite e exporta CSV. O maps gera o PNG da região. |
core/persistence.py, core/maps.py |
| ④ Exposição | A API FastAPI serve consultas, estatísticas, CSVs e mapas. O frontend consome a API e mostra o dashboard. | api/main.py, frontend/ |
Para cada combinação data × análise × previsão × variável × nível × região, o pipeline
chama fetch_filtered_grib() de core/downloader.py, que monta uma URL para o endpoint
filter da NOAA pedindo apenas aquele recorte:
https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl?file=gfs.t00z.pgrb2.0p25.f000&dir=/gfs.20260807/00/atmos&var_TMP=on&lev_1000_mb=on&leftlon=-56&rightlon=-42&toplat=-18&bottomlat=-28
Os parâmetros são preenchidos automaticamente a partir do catálogo NOAA_FILTER_VARS
(em core/downloader.py), que mapeia cada código interno ao nome GRIB (ex.: temp → TMP,
umidadeRel → RH, u/v → UGRD/VGRD, o3 → O3MR, total_o3 → TOZNE,
precipRate → PRATE, chuvaNaoConvec → APCP, categChuva → CRAIN,
nuvemMistura → CLWMR) e ao tipo de nível (que define o seletor lev_*_mb=on,
lev_surface, lev_mean_sea_level ou lev_*_m_above_ground; o total_o3 não usa seletor de
nível). As variáveis derivadas vento/ventoSup não têm entrada no filter — o pipeline baixa
as componentes u/v e calcula a magnitude localmente.
Antes de baixar, o pipeline verifica se o ciclo existe na NOAA (requisição HEAD ao arquivo)
— ciclos indisponíveis são pulados com aviso. Se o arquivo já estiver em
data/grib/<data>/<análise>/, ele é reutilizado (o pipeline é idempotente, ideal para
agendamentos). Cada GRIB baixado segue para core/grib_reader.py → core/processor.py
(recorte da região + estatísticas) → SQLite/CSV → mapa PNG.
No fim do pipeline, core/metar.py (fetch_and_store()) consulta a AviationWeather com
todos os códigos ICAO do registro local DEFAULT_STATIONS:
https://aviationweather.gov/api/data/metar?ids=SBGR,SBGL,SBBR,...&format=json
Cada boletim JSON é então processado automaticamente:
- Decodificado para um resumo legível (
_decoded): temperatura, ponto de orvalho, vento, visibilidade, QNH, nuvens e categoria de voo; - Corrigido quanto ao estado (a API às vezes devolve o estado errado, ex.: SBGR como "PR"
— o registro local
DEFAULT_STATIONScorrige para "SP"); - Persistido no SQLite (
save_metar_report+upsert_station); - Snapshotted como JSON em
data/metar/<CODIGO>/.
Passe --skip-metar no pipeline se não quiser essa etapa.
| Funcionalidade | Descrição |
|---|---|
| 📥 Ingestão de dados reais | GFS (NOAA) por variável/região + METAR ao vivo |
| 🌬️ Vento resultante | vento/ventoSup calculados a partir das componentes u/v do GFS |
| 🌧️ Precipitação | Taxa de chuva, precipitação acumulada e chuva categórica |
| ☁️ Nuvens | Cobertura total (nuvem) e razão de mistura de nuvens (nuvemMistura) |
| 🌡️ Catálogo v2.1 | 47 variáveis (38 com dados GFS): termodinâmica, vento, nuvens, hidrometeoros, convecção, radar, visibilidade, solo, dinâmica e poluição |
| 🗺️ Mapas PNG | Mapas do Brasil com a distribuição espacial de cada variável |
| 🧮 Estatísticas | Mínimo, máximo e média por variável/região/nível |
| 💾 Persistência | SQLite para consultas + CSV para exportação + snapshots JSON de METAR |
| 🔌 API REST | FastAPI com documentação interativa automática em /docs |
| 📊 Dashboard web | Frontend simples com cartões, mapas, METAR e exportação CSV |
| ⚙️ Orquestração | Scripts prontos: pipeline, servidor e validação (e Docker opcional) |
Stack: Python · FastAPI · SQLite · matplotlib + Basemap · pygrib · Shell Script
- Python 3.11+ e
pip - Internet — a ingestão baixa dados reais da NOAA e da AviationWeather
- SQLite — já embutido no Python, não precisa instalar nada
Instale as bibliotecas de sistema necessárias para o pygrib (eccodes) e o Basemap (proj/geos):
sudo apt-get install -y gcc g++ libeccodes-dev libproj-dev libgeos-dev libsqlite3-dev curl🐧 Se você usa Windows ou macOS, o caminho é usar o Docker (veja a seção Docker).
Siga na ordem. No fim você terá um servidor rodando com dados reais.
python -m venv ~/envs/met
source ~/envs/met/bin/activatepip install -r requirements.txtcp .env.example .envO arquivo .env já vem com valores padrão sensatos — você só precisa editá-lo se quiser mudar portas, URLs ou o banco.
PYTHONPATH=. python -c "import api.main, core.maps, core.metar, core.persistence; print('OK')"
⚠️ Importante: os scripts usam imports absolutos (core.*,api.*). Sempre rode comPYTHONPATH=.no comando.
A primeira vez, use um escopo pequeno para não bombardear a NOAA:
PYTHONPATH=. python scripts/process_data.py --date 20260807 --analysis 00 --forecast 00 --regions SP RJEsse comando baixa o ciclo das 00Z de 07/08/2026 para SP e RJ, processa as variáveis padrão, gera os mapas e ainda busca os METAR ao vivo.
💡 Quando quiser rodar tudo (todas as análises e previsões), use o atalho:
bash scripts/pipeline.sh
⚠️ Atenção: o escopo padrão é grande (4 análises × 4 previsões × variáveis × regiões = centenas de downloads).
bash scripts/server.sh start # ou: stop | restart | statusOu, em modo de desenvolvimento (com reload automático):
uvicorn api.main:app --host 0.0.0.0 --port 8000 --reloadAbra no navegador:
| O quê | Endereço |
|---|---|
| 🖥️ Frontend + Dashboard | http://localhost:8000/ |
| 📘 Documentação da API (Swagger) | http://localhost:8000/docs |
| 📑 Documentação alternativa (ReDoc) | http://localhost:8000/redoc |
Teste a API pelo terminal:
curl -s http://localhost:8000/health
curl -s "http://localhost:8000/api/v1/data/?variable=temp&level=1000®ion=SP"Copie .env.example para .env. Todas as variáveis têm padrões sensatos em core/config.py,
então o .env só é necessário para personalizar:
| Variável | Padrão | Descrição |
|---|---|---|
NOAA_BASE_URL |
https://nomads.ncep.noaa.gov/... |
Base do GFS completo |
NOAA_FILTER_URL |
https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl |
Endpoint filter (subconjuntos por região) |
NOAA_FTP_URL |
ftp://ftp.ncep.noaa.gov/... |
Alternativa FTP |
AVIATION_WEATHER_URL |
https://aviationweather.gov/api/data/metar |
Fonte dos boletins METAR |
SQLITE_DB_PATH |
data/sqlite/met_data.db |
Caminho do banco |
API_HOST |
0.0.0.0 |
Endereço do servidor |
API_PORT |
8000 |
Porta do servidor |
API_WORKERS |
4 |
Workers do uvicorn |
LOG_LEVEL |
INFO |
Nível de log |
📌 Todos os caminhos de arquivo são calculados a partir de
core/config.py(BASE_DIR), sem caminhos absolutos codificados. O própriocore/config.pycria os diretórios ao ser importado.
O pipeline (scripts/process_data.py) executa: download → processamento → SQLite → mapas → METAR.
🏭 A regra de ouro da fábrica: a API e o frontend são apenas a vitrine de atendimento — eles nunca saem à rua para buscar dados, somente mostram o que já está no estoque (SQLite e mapas). Todo dado novo entra pela porta da fábrica: o pipeline. Quer manter a vitrine sempre atualizada? Agende o pipeline — por exemplo, via
crona cada 6h, cobrindo os ciclos 00/06/12/18Z (veja a FAQ). E lembre:scripts/pipeline.shé só o porteiro — ele ativa o ambiente e chama oscripts/process_data.pypor você.
PYTHONPATH=. python scripts/process_data.py [opções]| Flag | Padrão | Descrição |
|---|---|---|
--date YYYYMMDD |
hoje, depois ontem | Data do ciclo GFS |
--analysis 00 06 |
todas (00 06 12 18) | Ciclos sinóticos (aceita vários) |
--forecast 00 06 |
todas (f000–f018) | Horas de previsão (aceita vários) |
--regions SP RJ |
SP RJ PR RS MG AM |
Regiões (18 disponíveis) |
--all-variables |
desligado | Processa as 47 variáveis do catálogo (as ausentes no GFS são puladas com erro logado) |
--skip-metar |
desligado | Não busca METAR |
- Escopo padrão é grande: 4 análises × 4 previsões × variáveis × regiões. Narrow com
--analysise--forecast. - Ciclos indisponíveis na NOAA são detectados e pulados automaticamente (com aviso no log).
- Arquivos já baixados são reutilizados (cache em
data/grib/<data>/<análise>/) — o pipeline é idempotente. - Regiões desconhecidas são silenciosamente ignoradas.
- Variáveis fora do produto GFS são registradas no log como erros (não derrubam o pipeline).
💡 O conjunto padrão de variáveis fica em
DEFAULT_VARIABLESno topo descripts/process_data.py: termodinâmica (ps,prnm,temp1000/850/500,temps,umidadeRel,umidadeEsp,alturaGeo), vento (u,v,vento850;ventoSup10 m;ventoRajada;cisalhamentoVertical), nuvens (nuvem,nuvemMistura), hidrometeoros (chuvaRazao,geloRazao,neveRazao,granizoRazao), convecção (cape,cin,indiceLift), radar (reflectividade,reflectividadeMax), visibilidade (visibilidade), solo (tempSolo,umidadeSolo), dinâmica (vorticidade,velVertical,velVerticalGeo,umidadePrecipitavel) e precipitação (precipRate,chuvaNaoConvec,categChuva). As variáveis de chuva (precipRate,chuvaNaoConvec) só têm valor em horários com chuva — em áreas/tempos secos os mínimos são0.
Meteorológicas (38): ps, prnm, temp, temps, nuvem, nuvemMistura,
chuvaNaoConvec, chuvaConvec, precipRate, categChuva, umidadeRel, umidadeEsp,
alturaGeo, u, v, uSupe, vSupe, vento, ventoSup, ventoRajada,
cisalhamentoVertical, chuvaRazao, geloRazao, neveRazao, granizoRazao, cape, cin,
indiceLift, reflectividade, reflectividadeMax, visibilidade, tempSolo, umidadeSolo,
aguaLiquidaSolo, vorticidade, velVertical, velVerticalGeo, umidadePrecipitavel
Poluição (9): o3, total_o3, no2, so2, co, pm25, pm10, aod, dust
⚠️ Importante: 38 variáveis têm dados no produto GFS pgrb2 0p25 e estão conectadas ao endpoint filter da NOAA (36 meteorológicas +o3,total_o3):ps,prnm,temp,temps,nuvem,nuvemMistura,umidadeRel,umidadeEsp,alturaGeo,u,v,uSupe,vSupe,vento,ventoSup,ventoRajada,cisalhamentoVertical,chuvaRazao,geloRazao,neveRazao,granizoRazao,cape,cin,indiceLift,reflectividade,reflectividadeMax,visibilidade,tempSolo,umidadeSolo,vorticidade,velVertical,velVerticalGeo,umidadePrecipitavel,precipRate,chuvaNaoConvec,categChuva.
ventoeventoSupsão derivadas: a resultante do vento (magnitude) é calculada emcore/processor.pya partir das componentesu/v(vento) euSupe/vSupe(ventoSup) — o GFS fornece apenas as componentes direcionais.- Chuva:
precipRate(Precipitation rate,PRATE),chuvaNaoConvec(Total precipitation,APCP) ecategChuva(Categorical rain,CRAIN) são confirmadas no inventáriovarMET.txte verificadas ao vivo no endpoint filter. OAPCPacumulado só existe a partir def006(nof000é vazio/zero) — por isso o pipeline loga erro nesse caso.- Nuvens: além da cobertura total
nuvem(TCDC), adicionamosnuvemMistura(Cloud mixing ratio,CLWMR) em níveis isobáricos.Da categoria poluição, somente
o3etotal_o3têm dados reais. As demais (no2,so2,co,pm25,pm10,aod,dust) echuvaConvecficam no catálogo como experimentais — o endpoint/data/variablesmarca isso no campoavailable, e o frontend só exibe as disponíveis.Essa lista foi confirmada pelo inventário
varMET.txt(dump ASCII do conteúdo do arquivo GRIB, na raiz do projeto) e verificada ao vivo contra o endpoint filter da NOAA. Testes garantem exatamente{o3, total_o3}como poluição disponível — então não altereAVAILABLE_IN_GFSemcore/variables.pypor conta própria.v2.1: as variáveis recomendadas no documento
analise_variaveis_meteorologicas_grib_025.txtforam mapeadas para os correspondentes do GFS pgrb2 0p25 e validadas ao vivo no endpoint filter: termodinâmica (umidadeEsp,alturaGeo), vento (ventoRajada,cisalhamentoVertical), hidrometeoros (chuvaRazao,geloRazao,neveRazao,granizoRazao), convecção (cape,cin,indiceLift), radar (reflectividade,reflectividadeMax), visibilidade (visibilidade), solo (tempSolo,umidadeSolo;aguaLiquidaSolofica catálogo-only) e dinâmica (vorticidade,velVertical,velVerticalGeo,umidadePrecipitavel).
Níveis isobáricos suportados: 1000, 925, 850, 700, 500, 300, 200, 100, 50, 30, 20, 10 hPa
Níveis de altura (uSupe/vSupe): 10, 20, 30, 40, 50, 80, 100 m
Camadas de solo (tempSolo, umidadeSolo): 0-0.1, 0.1-0.4, 0.4-1, 1-2 m
Superfície (ps, temps, total_o3): nível 0 (sem parâmetro level em consultas/mapas)
SP, RJ, AM, DF, PR, RS, MG, PA, PE, CE, SA, FOR, REC, SSA, BEL, BH, CWB, POA
Cada região é um retângulo de coordenadas (min/max de longitude e latitude) definido em
core/config.py (REGIOES). Inclui capitais e cidades com aeroportos.
| Caminho | Conteúdo |
|---|---|
data/grib/<data>/<análise>/ |
Arquivos GRIB baixados da NOAA (cache) |
data/sqlite/met_data.db |
Banco principal: dados processados + METAR |
data/csv/ |
Exportações CSV |
data/metar/ |
Snapshots JSON dos boletins METAR |
maps/ |
Mapas PNG gerados |
Os mapas seguem o padrão de nome:
GFS_<resolução>_<REGIÃO>_N<nível|SFC>_<variável>_<análise>_<data>_<previsão>.png
⚠️ Os códigos de variável podem conter underscores (total_o3,umidadeRel,uSupe). O parser de nomes emapi/routes/maps.py(_FILENAME_RE) já lida com isso.
A base das rotas é /api/v1 (exceto /health e /docs, que ficam na raiz).
| Método | Rota | Descrição |
|---|---|---|
| GET | /health |
Status do servidor e do banco (+ /health/ready) |
| GET | /api/v1/data/variables |
Catálogo das 47 variáveis (com campo available) |
| GET | /api/v1/data/regions |
As 18 regiões |
| GET | /api/v1/data/dashboard |
Resumo estatístico agregado |
| GET | /api/v1/data/available |
Variáveis/regiões/datas disponíveis no banco |
| GET | /api/v1/data/ |
Consulta de dados (?variable&level®ion&date&analysis&limit) |
| GET | /api/v1/data/latest |
Registro mais recente |
| GET | /api/v1/data/stats |
Estatísticas (mín/máx/média) |
| GET | /api/v1/data/levels/{var} |
Níveis disponíveis para a variável |
| GET | /api/v1/data/export/csv |
Exportação CSV |
| GET | /api/v1/maps/{var}/{region} |
Mapa PNG (?level&date&analysis) |
| GET | /api/v1/maps/list/{var}/{region} |
Lista de mapas disponíveis |
| GET | /api/v1/metar/stations |
Estações METAR |
| GET | /api/v1/metar/{code} |
Último METAR + decodificação |
| GET | /api/v1/metar/latest/all |
METAR de todas as estações |
| GET | /api/v1/info |
Metadados do app |
BASE=http://localhost:8000/api/v1
# Status
curl -s http://localhost:8000/health
# Temperatura em 1000 hPa na região SP
curl -s "$BASE/data/?variable=temp&level=1000®ion=SP"
# Estatísticas
curl -s "$BASE/data/stats?variable=temp&level=850®ion=SP"
# Exportar CSV
curl -s "$BASE/data/export/csv?variable=temp&level=850®ion=SP" -o dados.csv
# Baixar mapa PNG (data + análise juntas)
curl -s "$BASE/maps/temp/SP?level=850&date=20260807&analysis=00" -o mapa.png
# Último METAR de Guarulhos (SBGR)
curl -s "$BASE/metar/SBGR"
# Dashboard agregado
curl -s "$BASE/data/dashboard"💡 Dica: para variáveis de superfície (ex.:
ps), não use o parâmetrolevel— elas são gravadas com nível0. O frontend já lida com isso automaticamente.
O frontend é servido pela própria API em / e tem três áreas:
- Dashboard — cartões com total de registros, variáveis, regiões e estatísticas METAR; tabelas agregadas por variável e por região.
- Mapa — seleção de categoria (Meteorológicas/Poluição), variável, nível, região, data e análise; carrega o mapa PNG e mostra mín/máx/média; botão CSV exporta os dados.
- METAR — seleção de estação e visualização do boletim cru + decodificado.
⚠️ Os ativos estáticos são servidos sob/static. Oindex.htmlreferenciastatic/style.cssestatic/app.js(sem/na frente, e nãostyle.csspuro) — isso é garantido por testes, então não troque esses caminhos.
Você pode rodar sem instalar nada localmente:
docker compose up -d api # sobe a API (sempre ativa)
docker compose --profile manual run pipeline # roda o pipeline manualmente- O serviço
apisobe sozinho e fica de pé com healthcheck. - O serviço
pipelinesó roda quando você pede (via perfilmanual). data/emaps/são montados como volumes — os dados persistem entre execuções.- O Dockerfile instala as libs de sistema necessárias (eccodes, proj, geos) automaticamente.
# Suíte de testes end-to-end (TestClient in-process, sem servidor externo)
PYTHONPATH=. pytest tests/test_e2e.py -v
# Unit tests (sem rede/dados) — registro de variáveis e lógica do vento resultante
PYTHONPATH=. pytest tests/test_registry.py tests/test_processor.py -v
# Validação completa: dependências + pipeline real + banco + mapas + testes
bash scripts/validate.sh
⚠️ Os testes E2E leem o SQLite e os mapas — você precisa rodar o pipeline antes. Eles verificamtotal_records > 0, boletins METAR e PNGs. Depois de populado o banco, os testes não precisam de internet.
⚠️ Ovalidate.shroda o pipeline sem--date(usa o ciclo GFS mais recente encontrado pela NOAA). Para uma checagem totalmente determinística, rode o pipeline + pytest diretamente.
core/ Lógica de negócio (config, variáveis, regiões, download, GRIB, processamento, mapas, METAR)
api/ FastAPI (main, schemas, rotas: health, data, maps, metar)
frontend/ Interface web estática (index.html, app.js, style.css)
scripts/ process_data.py + wrappers shell (pipeline.sh, server.sh, validate.sh)
tests/ Testes end-to-end (test_e2e.py) + unit (test_registry.py, test_processor.py)
data/ Runtime (grib/, sqlite/, csv/, metar/) — ignorado pelo Git
maps/ Mapas PNG gerados — ignorado pelo Git
varMET.txt Inventário GRIB (dump ASCII) — referência das variáveis disponíveis
analise_variaveis_meteorologicas_grib_025.txt Documento de análise das variáveis (referência v2.1)
| Problema | Causa provável | Solução |
|---|---|---|
Pip falha em pygrib/basemap |
Faltam libs de sistema | sudo apt-get install -y gcc g++ libeccodes-dev libproj-dev libgeos-dev libsqlite3-dev |
ModuleNotFoundError: core... |
PYTHONPATH não aponta para o projeto |
Rode sempre com PYTHONPATH=. |
| Pipeline não encontra ciclo GFS | Data/ciclo ainda indisponível na NOAA | Use --date de um dia anterior ou rode mais tarde (o script tenta hoje e ontem) |
| Pipeline demora muito | Escopo padrão grande | Use --analysis 00 e --forecast 00 |
| Mapa retorna 404 | Não há mapa gerado para aquela seleção | Rode o pipeline para o conjunto; consulte /maps/list/{var}/{region} |
| Dados "vazios" de poluição | Variável não existe no GRIB pgrb2 | Só o3 e total_o3 estão confirmadas |
| Porta 8000 em uso | Outro processo | bash scripts/server.sh stop ou mude API_PORT no .env |
| Testes E2E falham sem dados | Banco/mapas ainda não populados | Rode o pipeline antes dos testes |
| METAR de Guarulhos aparece como "PR" | A AviationWeather devolve o estado errado | Já corrigido em core/metar.py (registro local DEFAULT_STATIONS) |
Porque são as únicas variáveis de poluição que existem no produto GFS pgrb2 0p25.
Confirmei isso cruzando o catálogo com o inventário varMET.txt (dump do arquivo GRIB).
As outras (no2, so2, co, pm25, pm10, aod, dust) ficam registradas no catálogo,
marcadas como available: false, prontas para quando a fonte tiver o dado.
Por padrão ele processa 4 análises × 4 previsões para cada variável e região — centenas de
downloads. Restrinja com --analysis 00 e --forecast 00, e use poucas regiões com --regions SP.
Os arquivos já baixados são reutilizados, então re-executar é mais rápido.
A API e o frontend não: eles leem o SQLite e os mapas já gerados. A internet só é necessária na ingestão (pipeline). Por isso os testes E2E funcionam offline após um pipeline.
É um dump ASCII do inventário do arquivo GRIB — a lista de variáveis/níveis que existem no
produto. É a fonte de verdade usada para decidir quais variáveis marcar como available.
Você não precisa abri-lo no dia a dia.
Não há scheduler embutido (de propósito). Use o cron do sistema:
0 */6 * * * bash /home/paulo/Documentos/meus_codigos/server_met/scripts/pipeline.shO exemplo acima roda a cada 6 horas (ciclos 00/06/12/18Z).
- Ela precisa existir no GFS pgrb2 0p25 (verifique no
varMET.txte, de preferência, teste a URL do endpoint filter ao vivo — alguns campos só existem a partir def006, como oAPCP); - Adicione o registro em
core/variables.py(nome GRIB, tipo de nível, conversão de unidade); - Se usar o endpoint filter, mapeie o short name em
NOAA_FILTER_VARSemcore/downloader.py; - Variáveis derivadas (calculadas de outras, como a resultante do vento) usam o campo
derived: ["u", "v"]no registro — o pipeline baixa as componentes e combina emcore/processor.py(combine_wind_resultant); - Adicione em
AVAILABLE_IN_GFSsomente se o dado realmente existir — os testes E2E garantem que as variáveis de poluição disponíveis sejam exatamente{o3, total_o3}.
Significa que não há PNG para aquela combinação variável/região/nível/data/análise.
Rode o pipeline para esse conjunto (ex.: --date 20260807 --analysis 00 --forecast 00 --regions SP)
e confira em /maps/list/{var}/{region}.
Não. A API é somente leitura e, em ambiente local, não exige autenticação.
Para expor em produção, coloque atrás de um proxy com HTTPS e controle de acesso.
Um erro conhecido da AviationWeather: ela às vezes devolve o estado errado no nome da
estação (ex.: Guarulhos → "PR"). O core/metar.py corrige o nome usando o registro local
DEFAULT_STATIONS, e um teste garante que SBGR fique como "SP".
Reais. O pipeline baixa as previsões vigentes do modelo GFS da NOAA e boletins METAR ao vivo da AviationWeather. A qualidade depende da disponibilidade dessas fontes (ciclos indisponíveis são pulados com aviso).
data/emaps/são ignorados pelo Git (artefatos gerados em execução).- Para produção, use
bash scripts/server.sh startou Docker. - A API é somente leitura e não exige autenticação em ambiente local.
- Quer saber mais? A documentação interativa da API está em
/docsquando o servidor estiver no ar.
Feito com ☕, Python e dados abertos da NOAA. 🛰️