Hola habr
Érase una vez, cuando un teléfono móvil costaba $ 2000 y un minuto de llamada costaba 50 centavos, había algo tan popular como la paginación. Luego, la conexión se hizo más barata, y el buscapersonas primero cambió del prestigioso atributo de una persona de negocios al prestigioso atributo de un servicio de mensajería o secretaria, y luego esta tecnología desapareció casi por completo.
Para aquellos que recuerdan el chiste "leyeron el buscapersonas, pensaron mucho" y quisieron descubrir cómo funciona, continuaron bajo el corte. Para aquellos que quieren entender aún más en detalle, la
segunda parte está disponible.
Información general
Para aquellos que han olvidado o nacieron después de la década de 2000, recordaré brevemente las ideas principales.
Desde el punto de vista del usuario, la comunicación de paginación tiene dos grandes ventajas, que en algunos casos siguen siendo relevantes:
- La comunicación es unidireccional, sin ninguna confirmación, por lo tanto, es imposible sobrecargar la red de búsqueda, su rendimiento no depende del número de suscriptores. Los mensajes simplemente se transmiten secuencialmente "tal cual", y el localizador los recibe si el número del destinatario coincide con el número del localizador.
- El dispositivo receptor es muy simple, de modo que el localizador puede funcionar sin recargarse hasta un mes con 2 baterías AA normales.
Existen dos estándares principales para enviar mensajes:
POCSAG (Grupo Asesor de Normalización del Código de la Oficina de Correos) y
FLEX . Los estándares no son nuevos en absoluto, POCSAG fue aprobado en 1982, velocidades compatibles de 512, 1200 y 2400 bit / s. Para la transmisión, se utiliza la modulación por desplazamiento de frecuencia (FSK) con un espaciado de frecuencia de 4.5KHz. El nuevo estándar FLEX (propuesto por Motorola en los años 90) admite velocidades de hasta 6400 bps y puede usar no solo FSK2, sino también FSK4.
Los protocolos son intrínsecamente bastante simples, y hace 20 años se escribieron decodificadores para ellos que podrían descifrar la señal de la entrada de una tarjeta de sonido (no se proporciona cifrado de mensajes, por lo que cualquiera puede leerlos con dicho programa, en principio).
Veamos como funciona.
Recepción de señales
Primero, necesitamos una muestra para decodificar. Tomamos una computadora portátil, un receptor rtl-sdr, una máquina del tiempo y recibimos la señal que necesitamos.

Porque modulación de frecuencia, el modo de recepción también establece FM. Usando HDSDR, grabamos la señal en formato WAV.
Veamos que tenemos. Descargue el archivo wav como una 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 (los bits se firman manualmente):

Como puede ver, todo es simple, e incluso "a simple vista" en Paint, puede dibujar bits donde "0" y donde "1". Pero hacer esto para todo el archivo sería demasiado largo, el proceso necesita ser automatizado.
Si aumenta el gráfico, puede ver que el ancho de cada "bit" es de 20 muestras, que a una frecuencia de muestreo del archivo wav de 24000 muestras / s corresponde a una velocidad de 1200 bits / s. Encontramos en la señal el lugar de transición a través de cero: este será el comienzo de la secuencia de bits. Mostraremos marcadores en la pantalla para verificar que los bits coincidan.
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
Como puede ver, la coincidencia no es perfecta (las frecuencias del transmisor y el receptor siguen siendo ligeramente diferentes), pero es suficiente para la decodificación.

Para señales largas, habría que introducir un algoritmo de ajuste de frecuencia, pero esto no es necesario en este caso.
Y el último paso es traducir la matriz de wav a una secuencia de bits. Aquí también todo es simple, ya conocemos la longitud de un bit, si los datos para este período son positivos, agregue "1", de lo contrario "0" (edición - como resultó, la señal necesitaba ser revertida, por lo que 0 y 1 fueron 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)
Quizás el código pueda optimizarse abandonando el bucle, aunque en este caso no es crítico.
El resultado es una secuencia terminada de bits (como una cadena) que guarda nuestro mensaje.
1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010110
010101010101010101010101010101010101010101010101010100111110011010010000101001101
100001111010100010011100000110010111011110101000100111000001100101110111101
01000100111000001100101110111101010001001110000011001011101111010101000100111
000001100101110111101010001001110000011001011101111010100010011100000110010
011011110101000100111000001100101110111101010001001110000011001011101111010
100010011100000110010111011110101000100111000001100101110111101010001001110
...
111101111Decodificación
Una secuencia de bits es mucho más conveniente que solo un archivo wav; ya puede extraer cualquier información de él. Dividimos el archivo en bloques de 4 bytes y obtenemos una secuencia más comprensible:
1010101010101010101010101010101010
1010101010101010101010101010101010
1010101010101010101010101010101010
1010101010101010101010101010101010
01111100110100100001010011011000
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
00001000011011110100010001101000
10000011010000010101010011010100
01111100110100100001010111011000
11110101010001000001000000111000
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
00100101101001011010010100101111Eso es todo lo que podemos extraer del archivo, queda por entender lo que significan estas líneas. Abra la documentación para el formato, que está disponible
en formato PDF .

Todo está más o menos claro. El encabezado del mensaje consiste en un bloque largo "10101010101" que se necesita para que el buscapersonas abandone el "modo de suspensión". El mensaje en sí consiste en bloques Batch-1 ... Batch-N, cada uno de los cuales comienza con una secuencia FSC única (resaltada en negrita en el texto). Además, como se puede ver en el manual, si la línea comienza con "0", esta es la dirección del destinatario. La dirección está conectada al localizador, y si no coincide, el localizador simplemente ignorará el mensaje. Si la línea comienza con "1", entonces este es realmente un mensaje. Tenemos dos de esas líneas.
Ahora mira cada bloque. Vemos códigos inactivos: bloques vacíos 01111 ... 0111 que no llevan información útil. Los eliminamos, queda muy poca información, todo lo que queda:
01111100110100100001010011011000 - Sincronización de trama
00001000011011110100010001101000 - Dirección
10000011010000010101010011010100 - Mensaje
01111100110100100001010111011000 - Sincronización de trama
11110101010001000001000000111000 - Mensaje
00100101101001011010010100101111 - DirecciónQueda por entender lo que hay dentro.
Buscamos más en el manual y descubrimos que los mensajes pueden ser digitales o de texto. Los mensajes digitales se almacenan en forma de códigos BCD de 4 bits, lo que significa que 5 caracteres pueden caber en 20 bits (todavía hay bits para el control, no los consideraremos). El mensaje también puede ser texto, en este caso se usa codificación de 7 bits, pero para el texto nuestro mensaje es demasiado pequeño: el número total de bits de mensaje no es un múltiplo de 7.
De las cadenas 10000011010000010101010011010100 y 11110101010001000001000000111000 obtenemos las siguientes secuencias de 4 bits:
1 0000 0110 1000 0010 10101 0011010100 - 0h 6h 8h 2h Ah
1 1110 1010 1000 1000 00100 0000111000 - Eh Ah 8h 8h 2h
Y finalmente, el último paso: buscamos en la documentación una tabla de correspondencia de caracteres.

Como puede ver, un mensaje digital solo puede contener números del 0 al 9, la letra U (“ugrent”), un espacio y un par de corchetes. Escribimos una función de salida simple para no leerlos manualmente:
def parse_msg(block):
Como resultado, obtenemos el mensaje transmitido "0682 *) * 882". Es difícil decir qué significa, pero dado que el formato admite mensajes digitales, probablemente alguien lo necesite.
Conclusiones
Como puede ver, el formato POCSAG es muy simple y, de hecho, puede decodificarse incluso en un cuaderno escolar. Y aunque ahora es de interés histórico, el análisis de dichos protocolos es muy útil desde un punto de vista cognitivo.
La
siguiente sección describe la decodificación de mensajes ASCII.