Compreendendo o protocolo de paginação POCSAG

Há muito tempo, quando um telefone celular custava cerca de US $ 2.000 e um minuto de chamada de voz era de 50 centavos, os pagers eram realmente populares. Mais tarde, os telefones celulares ficaram mais baratos, os preços de chamadas e SMS ficaram mais baixos e, finalmente, os pagers desapareceram.


Para pessoas que já possuíam um pager e desejam saber como ele funciona, este artigo será útil.

Informações principais


Para as pessoas que esqueceram os princípios ou nasceram depois de 2000x, lembrarei as principais idéias em breve.

A rede de comunicações de paginação possui algumas vantagens, às vezes importantes até agora:

- É uma comunicação unidirecional, sem qualquer tipo de confirmação, para que a rede não possa ser sobrecarregada - simplesmente não depende de vários usuários. As mensagens estão transmitindo continuamente "como estão", uma após a outra, e o pager está recebendo a mensagem se seu número (chamado Capcode) for igual ao número interno do dispositivo.

- O receptor é muito leve (literal e eletronicamente) e pode funcionar até um mês com 2 pilhas AA.

Existem dois padrões básicos de transmissão de mensagens - POCSAG (Grupo Consultivo para Padronização de Código Postal) e FLEX . Ambos os padrões são bastante antigos, o POCSAG foi fabricado em 1982, pode suportar velocidades de 512, 1200 e 2400 bit / s. Para transmitir o método FSK (chaveamento com mudança de frequência) é usado com uma separação de frequência de 4,5KHz. O FLEX é um pouco mais recente (foi fabricado pela Motorola na década de 90), pode funcionar com velocidade de até 6400 bits / s e pode usar o FSK2 e o FSK4.

Ambos os protocolos são geralmente muito fáceis, e há cerca de 20 anos foram criados decodificadores de PC que podem decodificar mensagens de uma porta serial da placa de som (não há criptografia suportada, para que todas as mensagens possam ser lidas por qualquer pessoa).

Vamos dar uma olhada, como funciona.

Recebendo um sinal


Primeiro, precisamos de um sinal para decodificar. Vamos pegar um laptop, receptor rtl-sdr, e pegá-lo.



A tecla de mudança de frequência é usada, então definiremos FM. Com o HDSDR, salvaremos um sinal no formato WAV.

Vamos verificar o que temos. Carregando o arquivo wav como uma matriz de dados Python:

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

Saída (bits adicionados manualmente):



Como podemos ver, é fácil e até "a olho nu" podemos desenhar bits no Paint, é fácil distinguir onde é "0" e onde é "1". Mas será muito tempo para fazê-lo manualmente, é hora de automatizar o processo.

Depois de ampliar o gráfico, podemos ver que cada bit tem uma largura de 20 amostras. Temos um arquivo wav de taxa de bits de 24.000 amostras por segundo, portanto a velocidade de chaveamento é de 1200 bits / s. Vamos encontrar uma posição de cruzamento zero - é o início da sequência de bits. Permite também adicionar marcadores para verificar se todos os bits estão em locais adequados.

 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 podemos ver, não é perfeitamente compatível (transmissor e receptor têm ligeiras frequências diferentes), mas é definitivamente o suficiente para decodificar.



Para sinais longos, provavelmente precisaremos do algoritmo de correção automática de frequência, mas para esse tipo de sinal não é crítico.

O último passo - precisamos traduzir o arquivo wav para a sequência de bits. Também é fácil, sabemos o tamanho de cada bit; se a soma dos dados for positiva, adicionaremos “1”, caso contrário, “0” (finalmente foi encontrado que um sinal precisa ser revertido, portanto, 0 e 1 foram substituídos) .

 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) 

Saída - sequência de bits adequada (em formato de string), que contém nossa mensagem.

101010101010101010101010101010101010101010101010101010101010101010101010101
010101010101010101010101010101010101010101010100111110011010010000101001101
100001111010100010011100000110010111011110101000100111000001100101110111101
010001001110000011001011101111010100010011100000110010111011110101000100111
000001100101110111101010001001110000011001011101111010100010011100000110010
011011110101000100111000001100101110111101010001001110000011001011101111010
100010011100000110010111011110101000100111000001100101110111101010001001110
...
111101111


Decodificando mensagens somente numéricas


Uma sequência de bits é muito mais conveniente que um arquivo wav, podemos extrair dados dele. Primeiro, vamos dividir os dados em blocos de 4 bytes.

10101010101010101010101010101010
10101010101010101010101010101010
10101010101010101010101010101010
10101010101010101010101010101010

01111100110100100001010011011000
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
00001000011011110100010001101000
10000011010000010101010011010100

01111100110100100001010111011000
11110101010001000001000000111000
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
00100101101001011010010100101111


Definitivamente, podemos ver um padrão. Agora precisamos descobrir o que cada parte significa. O manual do POCSAG está disponível em formato PDF , permite verificar a descrição da estrutura de dados.



Agora é muito mais claro. O cabeçalho contém um bloco longo "10101010101", é usado para "acordar" o pager no modo de suspensão. A própria mensagem contém os blocos Lote-1 ... Lote-N, cada bloco está iniciando na sequência exclusiva FSC. Então, como podemos ver no manual, se a string começar em "0", ela conterá o endereço do destinatário. O endereço em si (capcode) é armazenado é o pager e, se não corresponder, o pager ignorará a mensagem. Se uma sequência começar em "1", ela conterá o corpo da mensagem. No nosso exemplo, temos 2 strings desse tipo.

Não vamos verificar cada bloco. Também podemos ver códigos inativos - blocos vazios 01111 ... 0111, eles não possuem nenhuma informação útil. Depois de removê-los, obtemos apenas isso:

01111100110100100001010011011000 - Frame Sync
00001000011011110100010001101000 - Address
10000011010000010101010011010100 - Message

01111100110100100001010111011000 - Frame Sync
11110101010001000001000000111000 - Message
00100101101001011010010100101111 - Address


Precisamos descobrir o que há dentro.

Depois de verificar o manual, fica claro que existem dois tipos de mensagens - somente numérico e alfanumérico . As mensagens apenas numéricas são salvas como códigos BCD de 4 bits, então 20 bits podem conter 5 símbolos (também existem bits CRC, não os estamos usando no momento). Se a mensagem for alfanumérica, será usada a codificação ASCII de 7 bits. Esta mensagem é muito curta e, portanto, pode ser apenas uma mensagem numérica.

A partir das seqüências 10000011010000010101010011010100 e 11110101010001000001000000111000, podemos obter essas 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

O próximo passo é obter a tabela de decodificação no manual:



É óbvio que uma mensagem apenas numérica pode conter dígitos de 0 a 9, letra U ("ugrent"), espaço e dois parênteses. Vamos escrever um pequeno método para decodificá-lo:

 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() 

Finalmente, recebemos a mensagem "0682 *) * 882".

É difícil dizer o que significa, mas se as mensagens apenas numéricas forem usadas, alguém provavelmente precisará dela.

Decodificando mensagens alfanuméricas


O próximo passo, e mais interessante, é decodificar mensagens alfanuméricas. É mais interessante, porque, como saída, devemos obter o texto legível por humanos.

Primeiro, precisamos gravar uma mensagem novamente, usaremos o HDSDR. Como não conhecemos um tipo de mensagem antes da decodificação, gravamos apenas uma mensagem mais longa, podemos recebê-la e esperamos que ela contenha algum texto.



Depois de converter de wav para uma sequência de bits (veja um código Python acima), estamos obtendo o seguinte:



Algumas coisas interessantes que podemos ver imediatamente, a olho nu - como por exemplo, a sequência inicial 01010101010101 está repetindo duas vezes. Assim, essa mensagem não é apenas mais longa, ela literalmente contém duas mensagens, mescladas (um padrão não está negando isso, btw).

Como descobrimos antes, cada bloco de dados inicia a partir de uma sequência, chamada Frame Sync Code (01111100 ...), após o envio dos blocos de 32 bits. Cada bloco pode armazenar o endereço ou o corpo da mensagem.

Antes recebíamos as mensagens apenas numéricas, agora queremos ler as mensagens ASCII. Primeiro, precisamos distingui-los. Esses dados são salvos no campo "Bits de funções" (bits 20 a 21) - se os dois bits forem 00, será uma mensagem apenas numérica, se os bits forem 11, será uma mensagem de texto.

É interessante mencionar que esse campo de mensagem tem 20 bits, então é ideal colocar cinco blocos de 4 bits no caso de uma mensagem apenas numérica. Mas se tivermos uma mensagem ASCII de 7 bits, não podemos dividir de 20 a 7. É possível prever que a primeira versão do protocolo suporta apenas mensagens apenas numéricas (não esqueça que foi feita em 1982 e provavelmente os primeiros pagers de tubo nixie) não foram capazes de exibir mais ), e somente posteriormente foi adicionado suporte a mensagens ASCII. Por causa das razões herdadas, o padrão de enquadramento não foi alterado e os desenvolvedores usaram a abordagem fácil - eles apenas combinaram os bits "como estão", um após o outro. De cada mensagem, precisamos pegar 20 bits e mesclar para a próxima, finalmente podemos decodificar o corpo da mensagem.

Vamos ver um bloco da nossa mensagem (os espaços foram acrescentados para facilitar a leitura):

0 0001010011100010111111110010010
1 00010100000110110011 11100111001
1 01011010011001110100 01111011100
1 11010001110110100100 11011000100
1 11000001101000110100 10011110111
1 11100000010100011011 11101110000
1 00110010111011001101 10011011010
1 00011001011100010110 10011000010
1 10101100000010010101 10110000101
1 00010110111011001101 00000011011
1 10100101000000101000 11001010100
1 00111101010101101100 11011111010


Bit “0” Na primeira string nos mostra que é o campo de endereço e “11” em 20-21 bits nos mostra que a mensagem é realmente alfanumérica. Depois, pegamos 20 bits de cada string e os fundimos.

Esta é a nossa sequência de bits:

00010100000110110011010110100110011101001101000111011010010011000001101000
11010011100000010100011011001100101110110011010001100101110001011010101100
000010010101000101101110110011011010010100000010100000111101010101101


No POCSAG, o código ASCII de 7 bits é usado, portanto, dividimos uma string em 7 blocos de caracteres:

0001010 0000110 1100110 1011010 0110011 1010011 ...

Depois de tentar decodificá-lo (a tabela ASCII pode ser facilmente encontrada na Internet), obtemos ... apenas nada. Verificando o manual novamente, e aqui está a pequena frase "Os caracteres ASCII são colocados da esquerda para a direita (MSB para LSB). O LSB está transmitindo primeiro. " Portanto, o bit baixo está transmitindo primeiro - para a decodificação correta, precisamos reverter todas as strings.

É muito chato fazê-lo manualmente, então vamos escrever um código Python:

 def parse_msg(block): msgs = "" for cw in range(16): cws = block[32 * cw:32 * (cw + 1)] # Skip the idle word if cws.startswith("0111101010"): continue if cws[0] == "0": addr, type = cws[1:19], cws[19:21] print(" Addr:" + addr, type) else: msg = cws[1:21] print(" Msg: " + msg) msgs += msg # Split long string to 7 chars blocks bits = [msgs[i:i+7] for i in range(0, len(msgs), 7)] # Get the message msg = "" for b in bits: b1 = b[::-1] # Revert string value = int(b1, 2) msg += chr(value) print("Msg:", msg) print() 

Finalmente, estamos obtendo esta sequência (bits, códigos de símbolos e símbolos ASCII):

 0101000 40 ( 0110000 48 0 0110011 51 3 0101101 45 - 1100110 102 f 1100101 101 e 1100010 98 b 0101101 45 - 0110010 50 2 0110000 48 0 0110001 49 1 0111001 57 9 0100000 32 0110001 49 1 0110011 51 3 0111010 58 : 0110011 51 3 0110001 49 1 0111010 58 : 0110100 52 4 0110101 53 5 0100000 32 0101010 42 * 0110100 52 4 0110111 55 7 0110110 54 6 0101001 41 ) 0100000 32 1000001 65 A 1010111 87 W 1011010 90 Z 

Após a fusão, obtemos a sequência: "(03-feb-2019 13:31:45 * 476) AWZ". Como foi prometido, é bastante legível por humanos.

A propósito, é interessante mencionar que códigos ASCII de 7 bits são usados. Os símbolos de alguns alfabetos (alemão, cirílico, etc.) não podem ser codificados corretamente em 7 bits. Por que 7 bits? Provavelmente os engenheiros decidiram que "7 bits serão suficientes para todos", quem sabe ...

Conclusão


Foi realmente interessante investigar como o POCSAG funciona. É um dos protocolos raros em uso até agora que pode literalmente ser decodificado na folha de papel (e eu definitivamente não tentarei isso com TETRA ou GSM).

Com certeza, o protocolo POCSAG não está totalmente descrito aqui. A parte mais importante e interessante é feita, outras coisas não são tão emocionantes. Pelo menos, não há decodificação de códigos de captação e não há código de correção de erros (BCH Check Bits) - ele pode permitir corrigir até 2 bits errados na mensagem. Mas não havia objetivo de escrever outro decodificador POCSAG aqui, já existem o suficiente.

Para aqueles que desejam testar a decodificação real com o rtl-sdr, o aplicativo PDW freeware pode ser usado. Não requer instalação, basta apenas encaminhar o som do HDSDR para o PDW por meio do aplicativo Virtual Audio Cable.

Os resultados são assim:



(lembre-se de que a decodificação de mensagens de serviço público pode ser ilegal em alguns países e respeitar a privacidade dos destinatários)

Se alguém quiser obter mais informações sobre este tópico, estão disponíveis fontes do decodificador multimon-ng , que pode decodificar muitos protocolos, também POCSAG e FLEX.

Obrigado pela leitura.

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


All Articles