Desmontamos o protocolo de mensagens de pager POCSAG, parte 1

Oi Habr!

Era uma vez, quando um telefone celular custava US $ 2.000 e um minuto de ligação custava 50 centavos, havia algo tão popular como paginação. Então a conexão ficou mais barata, e o pager passou do atributo de prestígio de uma pessoa de negócios para o atributo de prestador de serviços de correio ou secretária, e então essa tecnologia desapareceu quase completamente.


Para aqueles que se lembram da piada “leem o pager, pensam muito” e querem descobrir como funciona, continuaram sob o corte. Para quem quer entender ainda mais detalhadamente, a segunda parte está disponível.

Informação geral


Para aqueles que esqueceram ou nasceram depois dos anos 2000, lembrarei brevemente das idéias principais.

Do ponto de vista do usuário, a comunicação por paginação tem duas grandes vantagens, que em alguns casos ainda são relevantes:

- A comunicação é unidirecional, sem qualquer confirmação, portanto, é impossível sobrecarregar a rede de paginação, seu desempenho não depende do número de assinantes. As mensagens são simplesmente transmitidas sequencialmente "como estão", e o pager as recebe se o número do destinatário corresponder ao número do pager.

- O dispositivo receptor é muito simples, para que o pager possa funcionar sem recarregar até um mês a partir de 2 pilhas AA comuns.

Existem dois padrões principais para o envio de mensagens - POCSAG (Grupo Consultivo para Padronização de Código Postal) e FLEX . Os padrões não são novos, o POCSAG foi aprovado em 1982, com velocidades suportadas de 512, 1200 e 2400 bit / s. Para a transmissão, é utilizado o chaveamento de mudança de frequência (FSK) com um espaçamento de frequência de 4,5 KHz. O novo padrão FLEX (proposto pela Motorola nos anos 90) suporta velocidades de até 6400 bps e pode usar não apenas o FSK2, mas também o FSK4.

Os protocolos são inerentemente bastante simples, e há 20 anos foram criados decodificadores para eles que poderiam descriptografar o sinal da entrada de uma placa de som (a criptografia de mensagens não é fornecida, para que qualquer pessoa possa lê-los com esse programa, em princípio).

Vamos ver como isso funciona.

Recebendo sinais


Primeiro, precisamos de uma amostra para decodificação. Pegamos um laptop, um receptor rtl-sdr, uma máquina do tempo e recebemos o sinal de que precisamos.



Porque modulação de frequência, o modo de recepção também define FM. Usando HDSDR, gravamos o sinal no formato WAV.

Vamos ver o que temos. Faça o download do arquivo wav como uma matriz usando Python:

from scipy.io import wavfile import matplotlib.pyplot as plt fs, data = wavfile.read("pocsag.wav") plt.plot(data) plt.show() 

Resultado (os bits são assinados manualmente):



Como você pode ver, tudo é simples, e mesmo "a olho nu" no Paint, você pode desenhar bits onde "0" e onde "1". Mas para fazer isso em todo o arquivo seria muito longo, o processo precisa ser automatizado.

Se você aumentar o gráfico, poderá ver que a largura de cada "bit" é de 20 amostras, que na frequência de amostragem do arquivo wav de 24000 amostras / s corresponde a uma velocidade de 1200 bits / s. Encontramos no sinal o local da transição através do zero - este será o começo da sequência de bits. Iremos exibir marcadores na tela para verificar se os bits correspondem.

 speed = 1200 fs = 24000 cnt = int(fs/speed) start = 0 for p in range(2*cnt): if data[p] < - 50 and data[p+1] > 50: start = p break # Bits frame bits = np.zeros(data.size) for p in range(0, data.size - cnt, cnt): bits[start + p] = 500 plt.plot(bits) 

Como você pode ver, a correspondência não é perfeita (as frequências do transmissor e do receptor ainda são um pouco diferentes), mas é o suficiente para decodificar.



Para sinais longos, seria necessário introduzir um algoritmo de ajuste de frequência, mas isso não é necessário neste caso.

E o último passo é converter o array de wav em uma sequência de bits. Tudo também é simples aqui, já sabemos a duração de um bit, se os dados para este período forem positivos, adicione "1", caso contrário, "0" (edição - como se viu, o sinal precisava ser revertido, então 0 e 1 foram revertidos).

 bits_str = "" for p in range(0, data.size - cnt, cnt): s = 0 for p1 in range(p, p+cnt): s += data[p] bits_str += "1" if s < 0 else "0" print("Bits") print(bits_str) 

Talvez o código possa ser otimizado abandonando o loop, embora neste caso não seja crítico.

O resultado é uma sequência finalizada de bits (como uma string) que salva nossa mensagem.

10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010 1010
0101010101010101010101010101010101010101010101010100111110011010010000101001101
100001111010100010011100000110010111011110101000100111000001100101110111101
01000100111000001100101110111101010001001110000011001011101111010101000100111
000001100101110111101010001001110000011001011101111010100010011100000110010
011011110101000100111000001100101110111101010001001110000011001011101111010
100010011100000110010111011110101000100111000001100101110111101010001001110
...
111101111

Decodificação


Uma sequência de bits é muito mais conveniente do que apenas um arquivo wav; você já pode extrair quaisquer dados dele. Dividimos o arquivo em blocos de 4 bytes e obtemos uma sequência mais compreensível:

1010101010101010101010101010101010
1010101010101010101010101010101010
1010101010101010101010101010101010
1010101010101010101010101010101010
01111100110100100001010011011000
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
00001000011011110100010001101000
10000011010000010101010011010100
01111100110100100001010111011000
11110101010001000001000000111000
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
00100101101001011010010100101111

É tudo o que podemos extrair do arquivo, resta entender o que essas linhas significam. Abra a documentação para o formato, disponível em PDF .



Tudo é mais ou menos claro. O cabeçalho da mensagem consiste em um bloco longo "10101010101", necessário para que o pager saia do "modo de suspensão". A mensagem em si consiste em blocos Lote-1 ... Lote-N, cada um dos quais começa com uma sequência FSC exclusiva (destacada em negrito no texto). Além disso, como pode ser visto no manual, se a linha começar com "0", esse é o endereço do destinatário. O endereço é conectado ao próprio pager e, se não corresponder, o pager simplesmente ignorará a mensagem. Se a linha começar com "1", então esta é realmente uma mensagem. Temos duas dessas linhas.

Agora olhe para cada bloco. Vemos códigos inativos - blocos vazios 01111 ... 0111 que não carregam informações úteis. Nós os excluímos, resta muito pouca informação, tudo o que resta:

01111100110100100001010011011000 - Sincronização de quadros
00001000011011110100010001101000 - Endereço
10000011010000010101010011010100 - Mensagem

01111100110100100001010111011000 - Sincronização de quadros
11110101010001000001000000111000 - mensagem
00100101101001011010010100101111 - Endereço

Resta entender o que está dentro.

Examinamos mais adiante no manual e descobrimos que as mensagens podem ser digitais ou de texto. As mensagens digitais são armazenadas na forma de códigos BCD de 4 bits, o que significa que 5 caracteres podem caber em 20 bits (ainda existem bits para controle, não serão considerados). A mensagem também pode ser texto; nesse caso, a codificação de 7 bits é usada, mas para o texto nossa mensagem é muito pequena - o número total de bits da mensagem não é um múltiplo de 7.

A partir das seqüências de caracteres 10000011010000010101010011010100 e 1111010101000100000100000000001000, obtemos as seguintes sequências de 4 bits:
1 0000 0110 1000 0010 10101 0011010100 - 0h 6h 8h 2h Ah
1 1110 1010 1000 1000 00100 0000111000 - Ah Ah 8h 8h 2h

E, finalmente, o último passo - procuramos na documentação uma tabela de correspondência de caracteres.



Como você pode ver, uma mensagem digital pode conter apenas os números de 0 a 9, a letra U ("ugrent"), um espaço e um par de colchetes. Escrevemos uma função de saída simples para não lê-las manualmente:

 def parse_msg(block): # 16 lines in a batch, each block has a length 32 bits for cw in range(16): cws = block[32 * cw:32 * (cw + 1)] if cws[0] == "0": addr = cws[1:19] print(" Addr:" + addr) else: msg = cws[1:21] print(" Msg: " + msg) size = 4 s = "" for ind in range(0, len(msg), size): bcd_s = msg[ind:ind + size] value = int(bcd_s, 2) symbols = "0123456789*U -)(" s += symbols[value] print(" ", s) print() 

Como resultado, obtemos a mensagem transmitida "0682 *) * 882". É difícil dizer o que isso significa, mas como o formato suporta mensagens digitais, provavelmente alguém precisa.

Conclusões


Como você pode ver, o formato POCSAG é muito simples e, de fato, pode ser decodificado mesmo em um caderno escolar. E embora agora seja de interesse histórico, a análise de tais protocolos é muito útil do ponto de vista cognitivo.

A próxima seção descreve a decodificação de mensagens ASCII.

Source: https://habr.com/ru/post/pt438602/


All Articles