Nous démontons le protocole des messages de pageur POCSAG, partie 1

Salut Habr!

Il était une fois, quand un téléphone portable coûtait 2000 $ et une minute d'appel coûtait 50 cents, il y avait une chose aussi populaire que la pagination. Ensuite, la connexion est devenue moins chère, et le téléavertisseur est d'abord passé de l'attribut prestigieux d'un homme d'affaires à l'attribut prestigieux d'un courrier ou d'une secrétaire, puis cette technologie a presque complètement disparu.


Pour ceux qui se souviennent de la blague, «lisez le téléavertisseur, réfléchissez beaucoup» et souhaitez comprendre comment cela fonctionne, a poursuivi la coupe. Pour ceux qui veulent comprendre encore plus en détail, la deuxième partie est disponible.

Informations générales


Pour ceux qui ont oublié ou qui sont nés après les années 2000, je rappellerai brièvement les principales idées.

Du point de vue de l'utilisateur, la communication par radiomessagerie présente deux grands avantages, qui dans certains cas sont toujours pertinents:

- La communication est unidirectionnelle, sans aucune confirmation, il est donc impossible de surcharger le réseau de radiomessagerie, ses performances ne dépendent pas du nombre d'abonnés. Les messages sont simplement diffusés séquentiellement «tels quels» et le pager les reçoit si le numéro du destinataire correspond au numéro de pager.

- L'appareil de réception est très simple, de sorte que le téléavertisseur peut fonctionner sans recharger jusqu'à un mois à partir de 2 piles AA ordinaires.

Il existe deux normes principales pour l'envoi de messages - POCSAG (Post Office Code Standardization Advisory Group) et FLEX . Les normes ne sont pas nouvelles du tout, POCSAG a été approuvé en 1982, prenant en charge des vitesses de 512, 1200 et 2400 bit / s. Pour la transmission, une modulation par décalage de fréquence (FSK) avec un espacement de fréquence de 4,5 KHz est utilisée. La nouvelle norme FLEX (proposée par Motorola dans les années 90) prend en charge des vitesses allant jusqu'à 6400 bps et peut utiliser non seulement FSK2, mais aussi FSK4.

Les protocoles sont intrinsèquement assez simples, et il y a 20 ans, des décodeurs ont été écrits pour eux qui pourraient décrypter le signal de l'entrée d'une carte son (le cryptage des messages n'est pas fourni, donc tout le monde peut les lire avec un tel programme, en principe).

Voyons comment cela fonctionne.

Réception de signaux


Tout d'abord, nous avons besoin d'un échantillon pour le décodage. Nous prenons un ordinateur portable, un récepteur rtl-sdr, une machine à remonter le temps et recevons le signal dont nous avons besoin.



Parce que modulation de fréquence, le mode de réception définit également FM. En utilisant HDSDR, nous enregistrons le signal au format WAV.

Voyons ce que nous avons. Téléchargez le fichier wav sous forme de tableau à l'aide de Python:

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

Résultat (les bits sont signés manuellement):



Comme vous pouvez le voir, tout est simple, et même «à l'œil nu» dans Paint, vous pouvez dessiner des bits où «0» et «1». Mais faire cela pour le fichier entier serait trop long, le processus doit être automatisé.

Si vous augmentez le graphique, vous pouvez voir que la largeur de chaque "bit" est de 20 échantillons, ce qui à une fréquence d'échantillonnage du fichier wav de 24000 échantillons / s correspond à une vitesse de 1200 bits / s. Nous trouvons dans le signal le lieu de transition par zéro - ce sera le début de la séquence de bits. Nous afficherons des marqueurs à l'écran pour vérifier que les bits correspondent.

 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) 

Comme vous pouvez le voir, la correspondance n'est pas parfaite (les fréquences de l'émetteur et du récepteur sont encore légèrement différentes), mais c'est assez pour le décodage.



Pour les signaux longs, un algorithme d'ajustement de fréquence devrait être introduit, mais ce n'est pas nécessaire dans ce cas.

Et la dernière étape consiste à traduire le tableau de wav en une séquence de bits. Tout est également simple ici, nous connaissons déjà la longueur d'un bit, si les données pour cette période sont positives, puis ajoutez «1», sinon «0» (édition - comme il s'est avéré que le signal devait être inversé, donc 0 et 1 ont été inversés).

 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) 

Peut-être que le code peut être optimisé en abandonnant la boucle, bien que dans ce cas ce ne soit pas critique.

Le résultat est une séquence finie de bits (sous forme de chaîne) qui enregistre notre message.

1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010
010101010101010101010101010101010101010101010101010100111110011010010000101001101
100001111010100010011100000110010111011110101000100111000001100101110111101
01000100111000001100101110111101010001001110000011001011101111010101000100111
000001100101110111101010001001110000011001011101111010100010011100000110010
011011110101000100111000001100101110111101010001001110000011001011101111010
100010011100000110010111011110101000100111000001100101110111101010001001110
...
111101111

Décodage


Une séquence de bits est beaucoup plus pratique qu'un simple fichier wav; vous pouvez déjà en extraire toutes les données. Nous divisons le fichier en blocs de 4 octets et obtenons une séquence plus compréhensible:

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

C'est tout ce que nous pouvons extraire du fichier, il reste à comprendre ce que ces lignes signifient. Ouvrez la documentation du format, disponible au format PDF .



Tout est plus ou moins clair. L'en-tête du message se compose d'un long bloc "10101010101" qui est nécessaire pour que le téléavertisseur quitte le "mode veille". Le message lui-même se compose des blocs Batch-1 ... Batch-N, chacun commençant par une séquence FSC unique (mise en évidence en gras dans le texte). De plus, comme on peut le voir dans le manuel, si la ligne commence par "0", alors c'est l'adresse du destinataire. L'adresse est câblée dans le pager lui-même, et si elle ne correspond pas, le pager ignorera simplement le message. Si la ligne commence par "1", c'est en fait un message. Nous avons deux lignes de ce type.

Regardez maintenant chaque bloc. Nous voyons des codes inactifs - des blocs vides 01111 ... 0111 qui ne contiennent pas d'informations utiles. Nous les supprimons, il reste très peu d'informations, tout ce qui reste:

01111100110100100001010011011000 - Frame Sync
00001000011011110100010001101000 - Adresse
10000011010000010101010011010100 - Message

01111100110100100001010111011000 - Frame Sync
11110101010001000001000000111000 - Message
00100101101001011010010100101111 - Adresse

Reste à comprendre ce qu'il y a à l'intérieur.

Nous regardons plus loin dans le manuel et découvrons que les messages peuvent être numériques ou textuels. Les messages numériques sont stockés sous forme de codes BCD 4 bits, ce qui signifie que 5 caractères peuvent tenir sur 20 bits (il y a encore des bits pour le contrôle, nous ne les considérerons pas). Le message peut également être du texte, dans ce cas, un codage 7 bits est utilisé, mais pour le texte, notre message est trop petit - le nombre total de bits du message n'est pas un multiple de 7.

A partir des chaînes 10000011010000010101010011010100 et 11110101010001000001000000111000, nous obtenons les séquences 4 bits suivantes:
1 0000 0110 1000 0010 10101 0011010100 - 0h 6h 8h 2h Ah
1 1110 1010 1000 1000 00100 0000111000 - Eh Ah 8h 8h 2h

Et enfin, la dernière étape - nous regardons dans la documentation une table de correspondance des personnages.



Comme vous pouvez le voir, un message numérique ne peut contenir que des chiffres de 0 à 9, la lettre U («ugrent»), un espace et une paire de crochets. Nous écrivons une simple fonction de sortie afin de ne pas les lire manuellement:

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

En conséquence, nous obtenons le message transmis "0682 *) * 882". Il est difficile de dire ce que cela signifie, mais comme le format prend en charge les messages numériques, alors probablement quelqu'un en a besoin.

Conclusions


Comme vous pouvez le voir, le format POCSAG est très simple et, en fait, peut être décodé même dans un cahier d'école. Et bien que maintenant il présente un intérêt plutôt historique, l'analyse de tels protocoles est très utile d'un point de vue cognitif.

La section suivante décrit le décodage des messages ASCII.

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


All Articles