Vou adivinhar e dizer que todos cujos amigos ou familiares já viajaram de avião usaram o Flightradar24 - um serviço gratuito e conveniente para rastrear voos em tempo real.

Na
primeira parte, as idéias básicas de operação foram descritas. Agora vamos mais longe e descobrir que dados estão transmitindo e recebendo exatamente entre a aeronave e uma estação terrestre. Também decodificaremos esses dados usando Python.
História
Deveria ser óbvio que os dados dos aviões não se destinam apenas aos usuários que desejam vê-los em seus smartphones. Este sistema é chamado ADS-B (vigilância dependente automática - transmissão) e foi projetado para a transmissão automática dos dados de informações da aeronave para o centro de controle - diferentes parâmetros, como coordenadas, velocidade, rumo, altitude e outros, estão enviando. Anteriormente, o expedidor podia ver apenas um ponto na tela do radar. E definitivamente não se tornou suficiente quando o número de aviões aumentou drasticamente.
Tecnicamente, o ADS-B consiste em um transmissor dentro da aeronave, que envia periodicamente quadros de dados de informações a uma frequência relativamente alta de 1090 MHz (existem outros modos, mas eles não são tão interessantes para nós, porque as coordenadas são transmitidas somente aqui). ) Claro, também há um receptor em algum lugar do aeroporto, mas para nós, assim como para os usuários, nosso próprio receptor é mais interessante.
Apenas para comparação, o primeiro sistema projetado para usuários comuns, o Airnav Radarbox, apareceu em 2007 e custou cerca de US $ 900, e cerca de US $ 250 por ano custaram uma assinatura de seus serviços de rede (a principal idéia desse sistema é coletar e compartilhar dados de
muitos receptores , um receptor independente é relativamente inútil).

Agora, quando os receptores RTL-SDR se tornam muito mais disponíveis, um dispositivo semelhante pode ser fabricado por US $ 30. Ele pode ser encontrado na
primeira parte do artigo , e iremos além e descreveremos o próprio protocolo - vamos ver como ele funciona.
Recebendo um sinal
Primeiro, precisamos gravar uma amostra de sinal. Todo o sinal tem apenas 120 microssegundos de duração e, para ver seus detalhes em uma "resolução" boa, é melhor ter rádio SDR com taxa de amostragem de pelo menos 5 MHz.

Após a gravação, estamos obtendo um arquivo WAV com uma taxa de amostragem de 5.000.000 de amostras / s, 30 segundos desse registro tem aproximadamente 500 MB de tamanho. Obviamente, é inútil ouvi-lo com seu media player favorito - o arquivo não contém um som, mas um sinal de rádio diretamente digitalizado - é exatamente assim que o Rádio Definido por Software funciona.
Podemos abrir e processar esse arquivo com Python. Aqueles que desejam fazer o experimento por conta própria, podem baixar uma amostra
deste link .
Vamos abrir um arquivo e ver o que está dentro.
from scipy.io import wavfile import matplotlib.pyplot as plt import numpy as np fs, data = wavfile.read("adsb_20190311_191728Z_1090000kHz_RF.wav") data = data.astype(float) I, Q = data[:, 0], data[:, 1] A = np.sqrt(I*I + Q*Q) plt.plot(A) plt.show()
Resultado: vemos alguns 'impulsos' sobre o ruído.

Cada "impulso" é um sinal, cuja estrutura é claramente visível se aumentarmos a resolução no gráfico.

Como podemos ver, a imagem é totalmente consistente com a descrição acima. Agora podemos processar esses dados.
Decodificação
Primeiro, precisamos ter um pouco de fluxo. O sinal em si é codificado com uma codificação manchester:

A partir das diferenças de meia mordida, podemos facilmente obter "0" e "1" reais.
bits_str = "" for p in range(8): pos = start_data + bit_len*p p1, p2 = A[pos: pos + bit_len/2], A[pos + bit_len/2: pos + bit_len] avg1, avg2 = np.average(p1), np.average(p2) if avg1 < avg2: bits_str += "0" elif avg1 > avg2: bits_str += "1"
A estrutura do sinal em si é assim:

Vamos ver os campos com mais detalhes.
DF (formato de downlink, 5 bits) - define o tipo de mensagem. Existem vários tipos deles:

(
origem da página )
Estamos interessados apenas no tipo DF17, porque apenas este contém as coordenadas da aeronave.
ICAO (24 bits) - é um código internacional exclusivo de aeronave. Podemos verificar a aeronave por seu código
neste site (infelizmente, o autor parou de atualizar o banco de dados, mas ainda é relevante). Por exemplo, para o código 3c5ee2, podemos ter as seguintes informações:
DATA (56 ou 112 bits) - são os dados em si, que decodificaremos. Os primeiros 5 bits de dados são o campo
Código de tipo , que contém o subtipo dos dados que estão sendo armazenados (não devem ser misturados ao campo
DF ). Existem muitos desses tipos:

(
origem da tabela )
Vejamos alguns exemplos.
Identificação da aeronaveUm exemplo em formato binário:
00100 011 000101 010111 000111 110111 110001 111000
Campos de dados:
+------+------+------+------+------+------+------+------+------+------+ | TC,5 | EC,3 | C1,6 | C2,6 | C3,6 | C4,6 | C5,6 | C6,6 | C7,6 | C8,6 | +------+------+------+------+------+------+------+------+------+------+
TC = 00100b = 4, e cada símbolo C1-C8 contém códigos, que devem corresponder aos índices nesta cadeia de caracteres:
#ABCDEFGHIJKLMNOPQRSTUVWXYZ ##### _ ################# 0123456789 ######
Após decodificar, é fácil obter o nome da aeronave: EWG7184
symbols = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######" code_str = "" for p in range(8): c = int(bits_str[8 + 6*p:8 + 6*(p + 1)], 2) code_str += symbols[c] print("Aircraft Identification:", code_str.replace('#', ''))
Posição no arA decodificação de nomes era simples, mas as coordenadas são mais complicadas. Eles são transmitidos na forma de 2 quadros, pares e ímpares. O código do campo TC = 01011b = 11.

Exemplo de quadros de dados pares e ímpares:
01011 000 000101110110 00 10111000111001000 10000110101111001 01011 000 000110010000 01 10010011110000110 10000011110001000
O cálculo das coordenadas em si usa uma fórmula um pouco complicada:

(
fonte )
Não sou especialista em GIS, portanto não sei de onde vem. Quem o conhece melhor, por favor escreva nos comentários.
O cálculo da altitude é mais simples - dependendo de um bit específico, ele pode ser representado como um múltiplo de 25 ou 100 pés.
Velocidade no arDataframe com TC = 19. O interessante aqui é que a velocidade pode ser relativa ao solo (mais precisa, denominada Velocidade do Solo) e Airspeed, medida pelo sensor de ar da aeronave (pode ser menos precisa por causa do vento). Muitos outros campos diferentes também são transmitidos:

(
fonte )
Conclusão
Como podemos ver, a tecnologia ADS-B se tornou uma simbiose interessante, quando um padrão é amplamente utilizável não apenas para profissionais, mas também para usuários comuns. Mas, definitivamente, o papel principal disso foi o barateamento da tecnologia dos receptores digitais SDR, que permite receber sinais com uma frequência maior que gigahertz em um dispositivo muito barato.
O próprio padrão, é claro, possui muito mais dados. Os interessados podem visualizar o PDF na página
ICAO ou visitar o
site mode-s.org já mencionado acima. É improvável que este artigo seja realmente usado pela maioria dos leitores, mas espero que, pelo menos a ideia geral de como ele funcione, seja agora mais claro.
A propósito, o decodificador ADS-B Python já existe, pode ser investigado
no github . Os proprietários dos receptores SDR também podem criar e executar o decodificador ADS-B pronto para uso a
partir desta página e (repetirei novamente) alguns detalhes que também apresentamos na
primeira parte deste artigo.
O código fonte do analisador, descrito acima, é fornecido sob o spoiler. Este é apenas um exemplo de teste que não pretende a qualidade da produção, mas em geral funciona e pode analisar o
arquivo WAV , gravado acima.
Código-fonte (Python) from __future__ import print_function from scipy.io import wavfile from scipy import signal import matplotlib.pyplot as plt import numpy as np import math import sys def parse_message(data, start, bit_len): max_len = bit_len*128 A = data[start:start + max_len] A = signal.resample(A, 10*max_len) bits = np.zeros(10*max_len) bit_len *= 10 start_data = bit_len*8
Espero que tenha sido útil, obrigado pela leitura.