Skip to content
אצלי
Go back

Do terminal ao mapa: ADS-B ao vivo na web com tar1090

Cockpit de aeronave com displays e instrumentos de voo iluminados
Foto de Anastasios Nastoulis na Pexels

Quinto artigo da série, e parte 2 do hands-on. No anterior o pipeline terminou funcionando, mas só em texto no terminal. Agora chega a recompensa visual: o mapa web ao vivo, estilo Flightradar, servido pelo próprio homelab.

Pra quem está chegando agora, o caminho até aqui em uma frase por artigo: o primeiro apresentou o projeto de gerar meus próprios dados do mundo físico morando embaixo da rota de Guarulhos; o segundo destrinchou o protocolo ADS-B, a mensagem de 112 bits que toda aeronave grita em 1090 MHz sem autenticação nenhuma; e o terceiro cobriu o hardware RTL-SDR v4, o que o separa dos clones e a instalação do driver no Arch e no Fedora.

O quarto artigo foi o hands-on de ponta a ponta no servidor EndeavourOS: validação do dongle em 1090 MHz com rtl_sdr, a escolha da antena certa pra polarização vertical do ADS-B, a compilação do readsb na unha (com dois patches pra domar o -Werror num código sem manutenção frente ao GCC atual), regra udev dedicada pro usuário de serviço, override do systemd com as flags corretas, e a prova final: aeronaves reais decodificadas com posição, altitude e velocidade via nc localhost 30003. Terminou com uma pendência declarada: os dados existiam só como streams brutos nas portas 30002 a 30005, sem interface visual. É essa pendência que este artigo resolve, e no caminho ela derruba uma decisão da parte 1: o fork do readsb vai ser trocado.

1. SDR++ (auxiliar visual de RF)

Já estava instalado (sdrpp-git, AUR) desde o terceiro artigo. Só precisou ser executado. Como o servidor tem uma sessão gráfica Wayland ativa (seat0/tty1), o app abre normalmente na tela:

sdrpp

Confirmado: os plugins dessa build são só fontes de hardware (rtl_sdr, hackrf, limesdr…) e demoduladores de rádio geral (FM, M17, pager, ATV, meteor). Não existe decodificador de ADS-B no SDR++. Ele serve pra visualizar o waterfall e o espectro em 1090 MHz manualmente, como conferência visual de que a antena está captando energia RF. Quem decodifica de fato é o readsb.

2. SatDump

Instalado via AUR:

yay -S satdump --answerclean All --answerdiff None --removemake --noconfirm

Optei pela versão estável (satdump 1.2.2), não a -git, por ser um projeto C++/CMake grande: menos chance de quebrar com o GCC do sistema. É focado em satélites (137 MHz, NOAA, Meteor), não em ADS-B; entra aqui só pra completar o stack que o primeiro artigo prometeu.

O build (CMake, C++, bastante plugin: inmarsat, cubesat, meteosat, GOES, NOAA/METOP, todos os backends de SDR) rodou em background e levou bem mais tempo que o readsb, uns 45 minutos. Compilou sem nenhum patch necessário. Como sempre, a etapa final de instalação precisou rodar manualmente no terminal:

sudo pacman -U ~/.cache/yay/satdump/satdump-1.2.2-5-x86_64.pkg.tar.zst

Apareceu um aviso de lint “pacote contém referência a $srcdir” durante o empacotamento. É informativo, sem efeito prático: alguns binários referenciam o caminho de build nos metadados.

Confirmado instalado:

pacman -Q satdump
# satdump 1.2.2-5
which satdump
# /usr/bin/satdump

3. Por que trocar o fork do readsb

Ao começar a configurar o tar1090 (o mapa web ao vivo), percebi que o readsb-git instalado na parte 1 (fork Mictronics, readsb-protobuf) grava os dados em protobuf binário (aircraft.pb), não em JSON:

file /run/readsb/aircraft.pb
# aircraft.pb: data

xxd /run/readsb/aircraft.pb | head -5
# 00000000: 08a0 b88f d306 10a9 377a c701 08a2 8192  ........7z......
# 00000010: 0712 0854 414d 3335 3930 2018 f666 20a3  ...TAM3590 ..f .

Dá pra reconhecer o callsign TAM3590 no meio dos bytes: os dados estão certos, só o formato é binário.

O tar1090 (e a maioria dos frontends web de ADS-B) espera JSON (aircraft.json). O fork Mictronics simplesmente não grava nesse formato, não tem flag pra isso.

A solução foi trocar para o readsb-wiedehopf-git, mantido pelo próprio autor do tar1090, que:

4. Removendo o fork antigo e instalando o novo

Os dois pacotes entram em conflito, então o readsb-git sai primeiro:

sudo pacman -R readsb-git

Build do novo fork, fora do cache do yay, mesma lição da parte 1 (dessa vez nem precisou de patch, compilou de primeira):

yay -G readsb-wiedehopf-git
cd ~/readsb-wiedehopf-git
makepkg -s --noconfirm

Instalação:

sudo pacman -U ~/readsb-wiedehopf-git/readsb-wiedehopf-git-3.16.15.r8.g0bfd047-1-x86_64.pkg.tar.zst

5. Reconfigurando pro novo fork

O pacote novo já vem com service e config próprios, com convenção de variáveis diferente do antigo (RECEIVER_OPTIONS/DECODER_OPTIONS/NET_OPTIONS/JSON_OPTIONS em vez do USER_OPTIONS único):

# /etc/default/readsb (gerado pelo pacote)
RECEIVER_OPTIONS="--device 0 --device-type rtlsdr --gain auto --ppm 0"
DECODER_OPTIONS="--max-range 450 --write-json-every 1"
NET_OPTIONS="--net --net-ri-port 30001 --net-ro-port 30002 --net-sbs-port 30003 --net-bi-port 30004,30104 --net-bo-port 30005"
JSON_OPTIONS="--json-location-accuracy 2 --range-outline-hours 24"

O JSON já vem habilitado por padrão (--write-json está no próprio readsb.service do pacote), a diferença chave em relação ao fork anterior.

Passos:

# Remover o override do systemd criado na parte 1 (referenciava $USER_OPTIONS,
# variável que não existe mais nesse pacote e quebraria o serviço novo)
sudo rm /etc/systemd/system/readsb.service.d/override.conf
sudo rmdir /etc/systemd/system/readsb.service.d

# Adicionar lat/lon reais na config nova (use as suas coordenadas)
sudo sed -i 's/--gain auto --ppm 0"/--gain auto --ppm 0 --lat -23.58 --lon -46.55"/' /etc/default/readsb

sudo systemctl daemon-reload
sudo systemctl restart readsb

A regra udev (99-readsb-rtlsdr.rules, GROUP="readsb") e o usuário de sistema continuaram funcionando sem alteração: o novo pacote cria o mesmo usuário readsb, com o mesmo uid.

Validação

journalctl -u readsb -n 15 --no-pager
Using lat: -23.58, lon: -46.55 (location accuracy: exact)
rtlsdr: using device #0: Generic RTL2832U OEM (RTLSDRBlog, Blog V4, SN 00000001)
Found Rafael Micro R828D tuner
RTL-SDR Blog V4 Detected
cat /run/readsb/aircraft.json
{ "now" : 1784929956.000, "messages" : 270, "aircraft" : [
{"hex":"e48e77","flight":"GLO2178 ","alt_baro":29875,"gs":435.0,"lat":-23.344178,"lon":-46.254120, ...},
{"hex":"e49246","flight":"TAM3994 ","alt_baro":13125,"gs":308.4,"lat":-23.399901,"lon":-46.175283, ...}

Agora sim, JSON de verdade, com voos reais (GLO2178, TAM3994), pronto pro tar1090 ler. E as ferramentas de terminal da parte 1 continuam funcionando normalmente sobre o fork novo:

Três terminais: viewadsb listando aeronaves com callsign e RSSI, a visão resumida ao vivo com três aeronaves e o stream SBS bruto via nc na porta 30003

6. Instalando o tar1090

Não existe pacote tar1090 no AUR. A instalação oficial é via script (wiedehopf/tar1090/install.sh), feito originalmente pra Debian/Ubuntu (usa apt-get). Antes de rodar, baixei e revisei o script inteiro (500 linhas) pra confirmar que era seguro e entender o que ele faz. Nunca rode um curl | sudo bash às cegas, ainda mais de script pensado pra outra distro.

Achado importante na revisão: o bloco que usa apt-get só roda se faltar git, jq ou curl no sistema. Como já havia git e curl, só faltava o jq. O resto do script (clonar os repos do tar1090 e do banco de dados de aeronaves, gerar configuração de webserver, criar serviço systemd) é genérico o suficiente pra funcionar em qualquer distro com systemd.

Dependências

sudo pacman -S --needed jq lighttpd
sudo mkdir -p /etc/lighttpd/conf.d

O mkdir é necessário porque o script só ativa o modo automático de configuração do lighttpd (lighttpd=yes) se achar esse diretório (convenção Debian de conf.d/conf-enabled/conf-available que o pacote do Arch não usa).

Rodando o instalador oficial

sudo bash ~/tar1090-install.sh

O script sozinho: clonou wiedehopf/tar1090 e wiedehopf/tar1090-db, detectou /run/readsb/aircraft.json como fonte de dados, gerou /etc/lighttpd/conf.d/88-tar1090.conf (aliases de URL pro /tar1090/) e criou e habilitou o serviço tar1090.service, um script que processa e compacta os dados do readsb pro formato que o frontend web lê.

Dois problemas encontrados depois de rodar o script

Problema 1: o lighttpd nunca subiu. O script só reinicia o lighttpd se ele já estava rodando antes; não habilita nem inicia um lighttpd recém-instalado do zero. Resultado: systemctl status lighttpd mostrava inactive (dead), apesar de tudo configurado.

Problema 2: o lighttpd.conf do Arch é minimalista e não carrega conf-enabled. O lighttpd.conf padrão do pacote Arch tem só o essencial (document-root, index-file), sem nenhuma linha incluindo o diretório onde o script (e o mkdir feito antes) colocou as configurações do tar1090. Sem isso, mesmo com o lighttpd rodando, ele nunca leria o 88-tar1090.conf.

Correção:

echo 'include_shell "cat /etc/lighttpd/conf-enabled/*.conf"' | sudo tee -a /etc/lighttpd/lighttpd.conf
sudo lighttpd -tt -f /etc/lighttpd/lighttpd.conf   # valida a config antes de subir
sudo systemctl enable --now lighttpd

Validação final

curl -sI http://localhost/tar1090/
# HTTP/1.1 200 OK

curl -s http://localhost/tar1090/data/aircraft.json | head -c 200
# { "now" : ..., "aircraft" : [{"hex":"e49511","flight":"GLO1238 ", ... "lat":-23.613876,"lon":-46.559397, ...

Mapa ao vivo funcionando no IP interno do servidor, em /tar1090/. E a recompensa visual depois de cinco artigos:

Interface web do tar1090 no navegador: mapa da região de Guarulhos com trilhas de voos, tabela com seis aeronaves e painel de detalhes do TAM8088, um Boeing 787-9 da LATAM, com foto, matrícula e telemetria completa

Clicando em qualquer aeronave, o painel lateral mostra tudo que o transponder transmite, enriquecido pelo banco de dados do tar1090: matrícula, companhia, tipo, rota, altitude com tendência, velocidade, proa e RSSI. Aqui um 787-9 da LATAM saindo de Guarulhos pra Amsterdã:

Painel detalhado do tar1090 pro voo TAM8078, Boeing 787-9 com rota GRU-AMS, sobre o mapa com trilhas coloridas por altitude e o círculo do receptor

O tooltip rápido, sem abrir o painel, já resolve a pergunta clássica de quem olha pro céu (“que avião é esse?”): um A330 da South African Airways subindo a 9.250 pés:

Mapa do tar1090 com tooltip do voo SAA227, Airbus A330 da South African Airways, mostrando matrícula, altitude, velocidade e RSSI

7. Estado final dos serviços

systemctl is-enabled lighttpd tar1090 readsb
# enabled
# enabled
# enabled

Todos habilitados, sobrevivem a reboot do servidor.

ServiçoFunção
readsbdecodifica ADS-B (fork wiedehopf, JSON)
tar1090processa e compacta os dados do readsb pro frontend web
lighttpdserve a página web em /tar1090/

E o pipeline inteiro, do sinal RF ao browser, cabe numa foto só: o mapa web de um lado, e do outro os mesmos aviões no viewadsb, na visão resumida e no stream SBS bruto:

Mapa web do tar1090 no navegador ao lado de três terminais no servidor: a visão ao vivo resumida, o viewadsb e o stream SBS bruto, todos mostrando as mesmas aeronaves

O que começou como “e se eu gerasse os meus próprios dados?” no primeiro artigo agora é um serviço de verdade no homelab: antena, RTL-SDR v4, readsb decodificando, tar1090 desenhando e lighttpd servindo, tudo habilitado no systemd.

Ainda haverá novos artigos e irei evoluir este lab…


Share this post on:

Next Post
Capturando ADS-B em 1090 MHz com a RTL-SDR v4