Wir zerlegen das Protokoll der Pager-Nachrichten POCSAG, Teil 1

Hallo Habr!

Es war einmal, als ein Mobiltelefon 2000 Dollar kostete und eine Minute Anruf 50 Cent kostete, gab es so etwas wie Paging. Dann wurde die Verbindung billiger, und der Pager verwandelte sich zuerst vom prestigeträchtigen Attribut eines Unternehmers in das prestigeträchtige Attribut eines Kuriers oder einer Sekretärin, und dann verschwand diese Technologie fast vollständig.


Für diejenigen, die sich an den Witz erinnern, "den Pager lesen, viel nachdenken" und herausfinden wollen, wie er funktioniert, weiter unter dem Schnitt. Für diejenigen, die noch mehr verstehen wollen, steht der zweite Teil zur Verfügung.

allgemeine Informationen


Für diejenigen, die vergessen haben oder nach den 2000er Jahren geboren wurden, werde ich mich kurz an die Hauptideen erinnern.

Aus Sicht des Benutzers hat die Paging-Kommunikation zwei große Vorteile, die in einigen Fällen immer noch relevant sind:

- Die Kommunikation erfolgt in eine Richtung ohne Bestätigung. Daher ist es unmöglich, das Paging-Netzwerk zu überlasten. Die Leistung hängt nicht von der Anzahl der Teilnehmer ab. Nachrichten werden einfach nacheinander "wie sie sind" gesendet, und der Pager empfängt sie, wenn die Empfängernummer mit der Pager-Nummer übereinstimmt.

- Das Empfangsgerät ist sehr einfach, so dass der Pager ohne Aufladen von bis zu einem Monat mit 2 normalen AA-Batterien arbeiten kann.

Es gibt zwei Hauptstandards für das Senden von Nachrichten: POCSAG (Post Office Code Standardization Advisory Group) und FLEX . Standards sind überhaupt nicht neu, POCSAG wurde bereits 1982 genehmigt und unterstützt Geschwindigkeiten von 512, 1200 und 2400 Bit / s. Für die Übertragung wird die Frequenzumtastung (FSK) mit einem Frequenzabstand von 4,5 kHz verwendet. Der neuere FLEX-Standard (von Motorola in den 90er Jahren vorgeschlagen) unterstützt Geschwindigkeiten von bis zu 6400 Bit / s und kann nicht nur FSK2, sondern auch FSK4 verwenden.

Die Protokolle sind von Natur aus recht einfach, und vor 20 Jahren wurden für sie Decoder geschrieben, die das Signal vom Eingang einer Soundkarte entschlüsseln können (eine Nachrichtenverschlüsselung ist nicht vorgesehen, sodass jeder sie grundsätzlich mit einem solchen Programm lesen kann).

Mal sehen, wie es funktioniert.

Signale empfangen


Zunächst benötigen wir ein Beispiel für die Dekodierung. Wir nehmen einen Laptop, einen RTL-SDR-Empfänger, eine Zeitmaschine und empfangen das Signal, das wir brauchen.



Weil Frequenzmodulation, Empfangsmodus auch FM eingestellt. Mit HDSDR zeichnen wir das Signal im WAV-Format auf.

Mal sehen, was wir haben. Laden Sie die WAV-Datei als Array mit Python herunter:

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

Ergebnis (Bits werden manuell signiert):



Wie Sie sehen können, ist alles einfach, und sogar „mit dem Auge“ in Paint können Sie Bits zeichnen, bei denen „0“ und „1“. Dies für die gesamte Datei zu tun, wäre jedoch zu lang. Der Prozess muss automatisiert werden.

Wenn Sie den Graphen vergrößern, sehen Sie, dass die Breite jedes „Bits“ 20 Abtastwerte beträgt, was bei einer Abtastfrequenz der WAV-Datei von 24000 Abtastungen / s einer Geschwindigkeit von 1200 Bits / s entspricht. Wir finden im Signal den Ort des Übergangs durch Null - dies ist der Beginn der Bitfolge. Wir werden Markierungen auf dem Bildschirm anzeigen, um zu überprüfen, ob die Bits übereinstimmen.

 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) 

Wie Sie sehen können, ist die Übereinstimmung nicht perfekt (die Frequenzen von Sender und Empfänger sind immer noch geringfügig unterschiedlich), aber für die Dekodierung völlig ausreichend.



Für lange Signale müsste ein Frequenzanpassungsalgorithmus eingeführt werden, der in diesem Fall jedoch nicht erforderlich ist.

Und der letzte Schritt besteht darin, das Array von wav in eine Bitsequenz zu übersetzen. Auch hier ist alles einfach, wir kennen bereits die Länge eines Bits. Wenn die Daten für diesen Zeitraum positiv sind, fügen Sie „1“ hinzu, andernfalls „0“ (Bearbeitung - wie sich herausstellte, musste das Signal umgekehrt werden, sodass 0 und 1 umgekehrt wurden).

 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) 

Möglicherweise kann der Code durch Verlassen der Schleife optimiert werden, obwohl dies in diesem Fall nicht kritisch ist.

Das Ergebnis ist eine fertige Folge von Bits (als Zeichenfolge), die unsere Nachricht speichert.

10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101
010101010101010101010101010101010101010101010101010100111110011010010000101001101
100001111010100010011100000110010111011110101000100111000001100101110111101
01000100111000001100101110111101010001001110000011001011101111010101000100111
000001100101110111101010001001110000011001011101111010100010011100000110010
011011110101000100111000001100101110111101010001001110000011001011101111010
100010011100000110010111011110101000100111000001100101110111101010001001110
...
111101111

Dekodierung


Eine Folge von Bits ist viel praktischer als nur eine WAV-Datei, Sie können bereits alle Daten daraus extrahieren. Wir teilen die Datei in Blöcke von 4 Bytes auf und erhalten eine verständlichere Reihenfolge:

101010101010101010101010101010101010
101010101010101010101010101010101010
101010101010101010101010101010101010
101010101010101010101010101010101010
01111100110100100001010011011000
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
00001000011011110100010001101000
10000011010000010101010011010100
01111100110100100001010111011000
11110101010001000001000000111000
01111010100010011100000110010111
01111010100010011100000110010111
01111010100010011100000110010111
00100101101001011010010100101111

Das ist alles, was wir aus der Datei extrahieren können. Es bleibt zu verstehen, was diese Zeilen bedeuten. Öffnen Sie die Dokumentation für das Format, das als PDF verfügbar ist.



Alles ist mehr oder weniger klar. Der Nachrichtenkopf besteht aus einem langen Block "10101010101", der benötigt wird, damit der Pager den "Schlafmodus" verlässt. Die Nachricht selbst besteht aus Batch-1 ... Batch-N-Blöcken, von denen jeder mit einer eindeutigen FSC-Sequenz beginnt (im Text fett hervorgehoben). Wie aus dem Handbuch ersichtlich ist, ist dies die Adresse des Empfängers, wenn die Zeile mit "0" beginnt. Die Adresse ist mit dem Pager selbst verbunden. Wenn sie nicht übereinstimmt, ignoriert der Pager die Nachricht einfach. Wenn die Zeile mit "1" beginnt, ist dies tatsächlich eine Nachricht. Wir haben zwei solche Zeilen.

Schauen Sie sich nun jeden Block an. Wir sehen Leerlaufcodes - leere Blöcke 01111 ... 0111, die keine nützlichen Informationen enthalten. Wir löschen sie, es sind nur noch sehr wenige Informationen übrig, alles was bleibt:

01111100110100100001010011011000 - Frame Sync
00001000011011110100010001101000 - Adresse
10000011010000010101010011010100 - Nachricht

01111100110100100001010111011000 - Frame Sync
11110101010001000001000000111000 - Nachricht
00100101101001011010010100101111 - Adresse

Es bleibt zu verstehen, was drin ist.

Wir schauen weiter im Handbuch nach und stellen fest, dass die Nachrichten digital oder textuell sein können. Digitale Nachrichten werden in Form von 4-Bit-BCD-Codes gespeichert, was bedeutet, dass 5 Zeichen in 20 Bit passen (es gibt noch Bits zur Steuerung, wir werden sie nicht berücksichtigen). Die Nachricht kann auch Text sein, in diesem Fall wird eine 7-Bit-Codierung verwendet, aber für Text ist unsere Nachricht zu klein - die Gesamtzahl der Nachrichtenbits ist kein Vielfaches von 7.

Aus den Zeichenfolgen 10000011010000010101010011010100 und 11110101010001000001000000111000 erhalten wir die folgenden 4-Bit-Sequenzen:
1 0000 0110 1000 0010 10101 0011010100 - 0h 6h 8h 2h Ah
1 1110 1010 1000 1000 00100 0000111000 - Eh Ah 8h 8h 2h

Und schließlich der letzte Schritt - wir sehen in der Dokumentation eine Entsprechungstabelle der Zeichen.



Wie Sie sehen können, kann eine digitale Nachricht nur die Zahlen 0–9, den Buchstaben U („ugrent“), ein Leerzeichen und ein Paar Klammern enthalten. Wir schreiben eine einfache Ausgabefunktion, um sie nicht manuell zu lesen:

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

Als Ergebnis erhalten wir die übertragene Nachricht "0682 *) * 882". Es ist schwer zu sagen, was es bedeutet, aber da das Format digitale Nachrichten unterstützt, braucht es wahrscheinlich jemand.

Schlussfolgerungen


Wie Sie sehen können, ist das POCSAG-Format sehr einfach und kann sogar in einem Schulheft dekodiert werden. Und obwohl es jetzt von eher historischem Interesse ist, ist die Analyse solcher Protokolle aus kognitiver Sicht sehr nützlich.

Im nächsten Abschnitt wird das Dekodieren von ASCII-Nachrichten beschrieben.

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


All Articles