Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B

Π—Π΄Ρ€Π°Π²Π΅ΠΉΡ‚Π΅, Π₯Π°Π±Ρ€. ВСроятно всСки, ΠΊΠΎΠΉΡ‚ΠΎ Π΅ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π» ΠΈΠ»ΠΈ посрСщал Ρ€ΠΎΠ΄Π½ΠΈΠ½ΠΈ ΠΈΠ»ΠΈ приятСли Π½Π° Π»Π΅Ρ‚ΠΈΡ‰Π΅, Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π» бСзплатния сСрвис Flightradar24. Π’ΠΎΠ²Π° Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΡƒΠ΄ΠΎΠ±Π΅Π½ Π½Π°Ρ‡ΠΈΠ½ Π·Π° прослСдяванС Π½Π° мСстополоТСниСто Π½Π° самолСта Π² Ρ€Π΅Π°Π»Π½ΠΎ Π²Ρ€Π΅ΠΌΠ΅.

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B

Π’ ΠΏΡŠΡ€Π²Π°Ρ‚Π° част бСшС описан ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡŠΡ‚ Π½Π° Ρ€Π°Π±ΠΎΡ‚Π° Π½Π° Ρ‚Π°ΠΊΡŠΠ² ΠΎΠ½Π»Π°ΠΉΠ½ сСрвис. Π‘Π΅Π³Π° Ρ‰Π΅ ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠΈΠΌ ΠΈ Ρ‰Π΅ Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ ΠΊΠ°ΠΊΠ²ΠΈ Π΄Π°Π½Π½ΠΈ сС ΠΏΡ€Π΅Π΄Π°Π²Π°Ρ‚ ΠΈ ΠΏΡ€ΠΈΠ΅ΠΌΠ°Ρ‚ ΠΎΡ‚ Π²ΡŠΠ·Π΄ΡƒΡ…ΠΎΠΏΠ»Π°Π²Π°Ρ‚Π΅Π»Π½ΠΎΡ‚ΠΎ срСдство Π΄ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌΠ½Π°Ρ‚Π° станция, ΠΈ Ρ‰Π΅ Π³ΠΈ Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€Π°ΠΌΠ΅ сами с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Python.

Π˜ΡΡ‚ΠΎΡ€ΠΈΡ

ΠžΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎ Π΅, Ρ‡Π΅ Π΄Π°Π½Π½ΠΈΡ‚Π΅ Π·Π° самолСтитС Π½Π΅ сС ΠΏΡ€Π΅Π΄Π°Π²Π°Ρ‚, Π·Π° Π΄Π° ΠΌΠΎΠ³Π°Ρ‚ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΠΈΡ‚Π΅ Π΄Π° Π³ΠΈ Π²ΠΈΠΆΠ΄Π°Ρ‚ Π½Π° смартфонитС си. БистСмата сС Π½Π°Ρ€ΠΈΡ‡Π° ADS–B (Automatic dependent surveillanceβ€”broadcast) ΠΈ слуТи Π·Π° Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π½ΠΎ ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅ Π½Π° информация Π·Π° Π²ΡŠΠ·Π΄ΡƒΡ…ΠΎΠΏΠ»Π°Π²Π°Ρ‚Π΅Π»Π½ΠΎΡ‚ΠΎ срСдство Π² диспСтчСрския Ρ†Π΅Π½Ρ‚ΡŠΡ€ β€” ΠΏΡ€Π΅Π΄Π°Π²Π°Ρ‚ сС ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ΠΈ, посока, скорост, височина ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ Π΄Π°Π½Π½ΠΈ. ΠŸΡ€Π΅Π΄ΠΈ появата Π½Π° Ρ‚Π°ΠΊΠΈΠ²Π° систСми, Π΄ΠΈΡΠΏΠ΅Ρ‚Ρ‡Π΅Ρ€ΡŠΡ‚ моТСшС Π΄Π° Π²ΠΈΠΆΠ΄Π° само Ρ‚ΠΎΡ‡ΠΊΠ° Π½Π° Ρ€Π°Π΄Π°Ρ€Π°. Π’ΠΎΠ²Π° стана Π½Π΅Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ, ΠΊΠΎΠ³Π°Ρ‚ΠΎ самолСтитС станаха Ρ‚Π²ΡŠΡ€Π΄Π΅ ΠΌΠ½ΠΎΠ³ΠΎ.

ВСхничСски, ADS-B сС ΡΡŠΡΡ‚ΠΎΠΈ ΠΎΡ‚ ΠΏΡ€Π΅Π΄Π°Π²Π°Ρ‚Π΅Π» Π½Π° Π²ΡŠΠ·Π΄ΡƒΡ…ΠΎΠΏΠ»Π°Π²Π°Ρ‚Π΅Π»Π½ΠΎΡ‚ΠΎ срСдство, ΠΊΠΎΠΉΡ‚ΠΎ ΠΏΠ΅Ρ€ΠΈΠΎΠ΄ΠΈΡ‡Π½ΠΎ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ с информация Π½Π° Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ висока чСстота ΠΎΡ‚ 1090 ΠœΠ“Ρ† (ΠΈΠΌΠ° ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ Ρ€Π΅ΠΆΠΈΠΌΠΈ, Π½ΠΎ Ρ‚Π΅ Π½Π΅ Π½ΠΈ интСрСсуват, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ΠΈΡ‚Π΅ сС ΠΏΡ€Π΅Π΄Π°Π²Π°Ρ‚ само Ρ‚ΡƒΠΊ). Π Π°Π·Π±ΠΈΡ€Π° сС, освСн прСдаватСля, ΠΈΠΌΠ° ΠΈ ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΠΊ някъдС Π½Π° Π»Π΅Ρ‚ΠΈΡ‰Π΅Ρ‚ΠΎ, Π½ΠΎ Π·Π° нас, ΠΊΠ°Ρ‚ΠΎ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΠΈ, интСрСсСн Π΅ Π½Π°ΡˆΠΈΡΡ‚ собствСн ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΠΊ.

Π—Π° сравнСниС, ΠΏΡŠΡ€Π²Π°Ρ‚Π° Ρ‚Π°ΠΊΠ°Π²Π° систСма, Airnav Radarbox, ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Π° Π·Π° ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΠΈ, сС появи ΠΏΡ€Π΅Π· 2007 Π³ΠΎΠ΄ΠΈΠ½Π° ΠΈ ΡΡ‚Ρ€ΡƒΠ²Π°ΡˆΠ΅ ΠΎΠΊΠΎΠ»ΠΎ 900$, Π° подписката Π·Π° ΠΌΡ€Π΅ΠΆΠΎΠ²ΠΈ услуги бСшС ΠΎΠΊΠΎΠ»ΠΎ 250$ Π½Π° Π³ΠΎΠ΄ΠΈΠ½Π°.

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B

ΠžΡ‚Π·ΠΈΠ²ΠΈ Π½Π° ΠΏΡŠΡ€Π²ΠΈΡ‚Π΅ руски собствСници ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅Ρ‚Π΅ Π½Π° Ρ„ΠΎΡ€ΡƒΠΌΠ° radioscanner. Π‘Π΅Π³Π°, ΠΊΠΎΠ³Π°Ρ‚ΠΎ масово сС появиха RTL-SDR ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΡ†ΠΈ, Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ устройство ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΡΡŠΠ±Π΅Ρ€Π΅ Π·Π° 30$, ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ Π·Π° Ρ‚ΠΎΠ²Π° бСшС Π² ΠΏΡŠΡ€Π²Π°Ρ‚Π° част. НиС ΠΎΠ±Π°Ρ‡Π΅ Ρ‰Π΅ ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅ΠΌ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ към ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° β€” Π½Π΅ΠΊΠ° Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ.

ΠŸΡ€ΠΈΠ΅ΠΌ Π½Π° сигнали

ΠŸΡŠΡ€Π²ΠΎ, ΡΠΈΠ³Π½Π°Π»ΡŠΡ‚ трябва Π΄Π° бъдС записан. ЦСлият сигнал ΠΈΠΌΠ° ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠΈΡ‚Π΅Π»Π½ΠΎΡΡ‚ само 120 микросСкунди, Π·Π°Ρ‚ΠΎΠ²Π° Π·Π° ΠΊΠΎΠΌΡ„ΠΎΡ€Ρ‚Π½ΠΎ разясняванС Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΈΡ‚Π΅ ΠΌΡƒ, ΠΆΠ΅Π»Π°Ρ‚Π΅Π»Π΅Π½ Π΅ SDR ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΠΊ с чСстота Π½Π° дискрСтизация Π½Π΅ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠ° ΠΎΡ‚ 5 MHz.

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B

Π‘Π»Π΅Π΄ записванС ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅ WAV Ρ„Π°ΠΉΠ» с чСстота Π½Π° дискрСтизация 5000000 сСмпла/сСк, 30 сСкунди Ρ‚Π°ΠΊΠΎΠ²Π° записванС Β«Ρ‚Π΅ΠΆΠΈΒ» ΠΎΠΊΠΎΠ»ΠΎ 500Мб. Π‘Π»ΡƒΡˆΠ°Π½Π΅Ρ‚ΠΎ ΠΌΡƒ с мСдия ΠΏΠ»Π΅ΠΉΡŠΡ€ Π΅ Ρ€Π°Π·Π±ΠΈΡ€Π° сС Π±Π΅Π·ΠΏΠΎΠ»Π΅Π·Π½ΠΎ β€” Ρ„Π°ΠΉΠ»ΡŠΡ‚ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° Π½Π΅ Π·Π²ΡƒΠΊ, Π° Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ ΠΎΡ†ΠΈΡ„Ρ€ΠΎΠ²Π°Π½ радиосигнал β€” Ρ‚ΠΎΡ‡Π½ΠΎ ΠΏΠΎ Ρ‚ΠΎΠ·ΠΈ Π½Π°Ρ‡ΠΈΠ½ Ρ€Π°Π±ΠΎΡ‚ΠΈ Software Defined Radio.

Π©Π΅ ΠΎΡ‚Π²ΠΎΡ€ΠΈΠΌ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΈΠΌ Ρ„Π°ΠΉΠ»Π° с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Python. Π–Π΅Π»Π°Π΅Ρ‰ΠΈΡ‚Π΅ Π΄Π° СкспСримСнтират сами, ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° изтСглят ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° запис. Π½Π° Π»ΠΈΠ½ΠΊΠ°.

Π©Π΅ Π·Π°Ρ€Π΅Π΄ΠΈΠΌ Ρ„Π°ΠΉΠ»Π° ΠΈ Ρ‰Π΅ Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊΠ²ΠΎ ΠΈΠΌΠ° Π²ΡŠΡ‚Ρ€Π΅.

from scipy.io import wavfile
import matplotlib.pyplot as plt
import numpy as np

fs, data = wavfile.read("adsb_20190311_191728Z_1090000kHz_RF.wav")
data = data.astype(float)
I, Q = data[:, 0], data[:, 1]
A = np.sqrt(I*I + Q*Q)

plt.plot(A)
plt.show()

Π Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚: Π²ΠΈΠΆΠ΄Π°ΠΌΠ΅ ясни «импулси» Π½Π° Ρ„ΠΎΠ½Π° Π½Π° ΡˆΡƒΠΌΠ°.

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B

ВсСки «импулс» Π΅ ΠΈΠΌΠ΅Π½Π½ΠΎ сигнал, структурата Π½Π° ΠΊΠΎΠΉΡ‚ΠΎ Π΅ Π΄ΠΎΠ±Ρ€Π΅ Π²ΠΈΠ΄ΠΈΠΌΠ°, Π°ΠΊΠΎ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠΌ Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° Π³Ρ€Π°Ρ„ΠΈΠΊΠ°Ρ‚Π°.

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B

ΠšΠ°ΠΊΡ‚ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π²ΠΈΠ΄ΠΈΠΌ, ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠ°Ρ‚Π° напълно ΡΡŠΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π° Π½Π° описаното ΠΏΠΎ-Π³ΠΎΡ€Π΅. МоТСм Π΄Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅ΠΌ към ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅.

Π”Π΅ΠΊΠΎΠ΄ΠΈΡ€Π°Π½Π΅

ΠŸΡŠΡ€Π²ΠΎ, трябва Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ битовия ΠΏΠΎΡ‚ΠΎΠΊ. Бамият сигнал Π΅ Π·Π°ΠΊΠΎΠ΄ΠΈΡ€Π°Π½ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° manchester encoding:

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B

ΠžΡ‚ Ρ€Π°Π·Π»ΠΈΠΊΠ°Ρ‚Π° Π½Π° Π½ΠΈΠ²Π°Ρ‚Π° Π² ΠΏΠΎΠ»ΡƒΠ±Π°ΠΉΡ‚ΠΈΡ‚Π΅ лСсно ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ Ρ€Π΅Π°Π»Π½ΠΈ Β«0Β» ΠΈ Β«1Β».

    bits_str = ""
    for p in range(8):
        pos = start_data + bit_len*p
        p1, p2 = A[pos: pos + bit_len/2], A[pos + bit_len/2: pos + bit_len]
        avg1, avg2 = np.average(p1), np.average(p2)
        if avg1  avg2:
            bits_str += "1"

Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° Π½Π° самия сигнал ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΠΏΠΎ слСдния Π½Π°Ρ‡ΠΈΠ½:

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B

НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΏΠΎΠ»Π΅Ρ‚Π°Ρ‚Π° ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ.

DF (Downlink Format, 5 Π±ΠΈΡ‚Π°) β€” опрСдСля Ρ‚ΠΈΠΏΠ° Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅Ρ‚ΠΎ. Има няколко Ρ‚ΠΈΠΏΠ°:

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B
(ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°)

Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΡƒΠ²Π° Π½ΠΈ само Ρ‚ΠΈΠΏ DF17, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΈΠΌΠ΅Π½Π½ΠΎ Ρ‚ΠΎΠΉ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ° ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ΠΈΡ‚Π΅ Π½Π° Π²ΡŠΠ·Π΄ΡƒΡˆΠ½ΠΎΡ‚ΠΎ съдно.

ICAO (24 Π±ΠΈΡ‚Π°) β€” ΠΌΠ΅ΠΆΠ΄ΡƒΠ½Π°Ρ€ΠΎΠ΄Π΅Π½ ΡƒΠ½ΠΈΠΊΠ°Π»Π΅Π½ ΠΊΠΎΠ΄ Π½Π° Π²ΡŠΠ·Π΄ΡƒΡˆΠ½ΠΎΡ‚ΠΎ съдно. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚Π΅ самолСта ΠΏΠΎ нСговия ΠΊΠΎΠ΄ Π½Π° сайта (Π·Π° съТалСниС, Π°Π²Ρ‚ΠΎΡ€ΡŠΡ‚ Π΅ спрял Π΄Π° Π°ΠΊΡ‚ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€Π° Π±Π°Π·Π°Ρ‚Π°, Π½ΠΎ тя всС ΠΎΡ‰Π΅ Π΅ Π°ΠΊΡ‚ΡƒΠ°Π»Π½Π°). НапримСр, Π·Π° ΠΊΠΎΠ΄ 3c5ee2 ΠΈΠΌΠ°ΠΌΠ΅ слСдната информация:

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B

ΠšΠΎΡ€Π΅ΠΊΡ†ΠΈΡ: Π² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΡ‚Π΅ ΠΏΠΎΠ΄ статията описаниСто Π½Π° ΠΊΠΎΠ΄Π° ICAO Π΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ΠΎ ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ, интСрСсуващитС сС ΠΏΡ€Π΅ΠΏΠΎΡ€ΡŠΡ‡Π²Π°ΠΌ Π΄Π° сС запознаят.

Π”ΠΠΠ˜ (56 ΠΈΠ»ΠΈ 112 Π±ΠΈΡ‚Π°) β€” самитС Π΄Π°Π½Π½ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ Ρ‰Π΅ Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€Π°ΠΌΠ΅. ΠŸΡŠΡ€Π²ΠΈΡ‚Π΅ 5 Π±ΠΈΡ‚Π° ΠΎΡ‚ Π΄Π°Π½Π½ΠΈΡ‚Π΅ β€” ΠΏΠΎΠ»Π΅ Type Code, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰ΠΎ ΠΏΠΎΠ΄Ρ‚ΠΈΠΏ Π½Π° ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°Π½ΠΈΡ‚Π΅ Π΄Π°Π½Π½ΠΈ (Π΄Π° Π½Π΅ сС Π±ΡŠΡ€ΠΊΠ° с DF). Π’Π°ΠΊΠΈΠ²Π° Ρ‚ΠΈΠΏΠΎΠ²Π΅ ΠΈΠΌΠ° доста:

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B
(ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°)

НСка Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ няколко ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ.

Π˜Π΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΡ Π½Π° Π²ΡŠΠ·Π΄ΡƒΡˆΠ½ΠΎ съдно

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π² Π±ΠΈΠ½Π°Ρ€Π΅Π½ Π²ΠΈΠ΄:

00100 011 000101 010111 000111 110111 110001 111000

ΠŸΠΎΠ»Π΅Ρ‚Π° Π½Π° Π΄Π°Π½Π½ΠΈΡ‚Π΅:

+------+------+------+------+------+------+------+------+------+------+
| TC,5 | EC,3 | C1,6 | C2,6 | C3,6 | C4,6 | C5,6 | C6,6 | C7,6 | C8,6 |
+------+------+------+------+------+------+------+------+------+------+

TC = 00100b = 4, всС символы C1-C8 ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‚ ΠΊΠΎΠ΄ΠΎΠ²Π΅, ΡΡŠΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π°Ρ‰ΠΈ Π½Π° индСкситС Π² стринга:
#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######

Π Π°Π·ΠΊΠΎΠ΄ΠΈΡ€Π°ΠΉΠΊΠΈ стринга, Π½Π΅ Π΅ Ρ‚Ρ€ΡƒΠ΄Π½ΠΎ Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ ΠΊΠΎΠ΄Π° Π½Π° самолСта: EWG7184

symbols = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######"
code_str = ""
for p in range(8):
     c = int(bits_str[8 + 6*p:8 + 6*(p + 1)], 2)
     code_str += symbols[c]
print("Π˜Π΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΡ Π½Π° самолСта:", code_str.replace('#', ''))

Π’ΡŠΠ·Π΄ΡƒΡˆΠ½Π° позиция

Ако с Π½Π°ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ΠΈΠ΅Ρ‚ΠΎ всичко Π΅ просто, Ρ‚ΠΎ с ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ΠΈΡ‚Π΅ Π΅ ΠΌΠ°Π»ΠΊΠΎ ΠΏΠΎ-слоТно. Π’Π΅ сС ΠΏΡ€Π΅Π΄Π°Π²Π°Ρ‚ ΠΏΠΎΠ΄ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π½Π° Ρ‡Π΅Ρ‚Π½ΠΈ ΠΈ Π½Π΅Ρ‡Π΅Ρ‚Π½ΠΈ ΠΊΠ°Π΄Ρ€ΠΈ. ΠšΠΎΠ΄ΡŠΡ‚ Π½Π° ΠΏΠΎΠ»Π΅Ρ‚ΠΎ TC = 01011b = 11.

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° Ρ‡Π΅Ρ‚Π½ΠΈ ΠΈ Π½Π΅Ρ‡Π΅Ρ‚Π½ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ:

01011 000 000101110110 00 10111000111001000 10000110101111001
01011 000 000110010000 01 10010011110000110 10000011110001000

Π‘Π°ΠΌΠΎΡ‚ΠΎ изчислСниС Π½Π° ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ΠΈΡ‚Π΅ сС случва ΠΏΠΎ доста слоТна Ρ„ΠΎΡ€ΠΌΡƒΠ»Π°:

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B
(ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ)

НС съм спСциалист ΠΏΠΎ Π“Π˜Π‘, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ ΠΎΡ‚ΠΊΡŠΠ΄Π΅ сС ΠΈΠ·Π²Π΅ΠΆΠ΄Π°, Π½Π΅ Π·Π½Π°ΠΌ. Ако някой Π·Π½Π°Π΅, моля ΠΏΠΈΡˆΠ΅Ρ‚Π΅ Π² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΡ‚Π΅.

Височината сС изчислява ΠΏΠΎ-лСсно β€” Π² зависимост ΠΎΡ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ Π±ΠΈΡ‚, ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС прСдставСна ΠΈΠ»ΠΈ ΠΊΡ€Π°Ρ‚Π½Π° Π½Π° 25, ΠΈΠ»ΠΈ Π½Π° 100 Ρ„ΡƒΡ‚Π°.

Π’ΡŠΠ·Π΄ΡƒΡˆΠ½Π° скорост

ΠŸΠ°ΠΊΠ΅Ρ‚ с TC=19. Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½ΠΎ Π΅, Ρ‡Π΅ скоростта ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΊΠ°ΠΊΡ‚ΠΎ Ρ‚ΠΎΡ‡Π½Π°, спрямо зСмята (Ground Speed), Ρ‚Π°ΠΊΠ° ΠΈ Π²ΡŠΠ·Π΄ΡƒΡˆΠ½Π°, ΠΈΠ·ΠΌΠ΅Ρ€Π²Π°Π½Π° ΠΎΡ‚ Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠ° Π½Π° самолСта (Airspeed). ΠŸΡ€Π΅Π΄Π°Π²Π°Ρ‚ сС ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ΠΏΠΎΠ»Π΅Ρ‚Π°:

Flightradar24 β€” ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ? Част 2, ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ADS-B
(ΠΈΠ·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ)

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

ΠšΠ°ΠΊΡ‚ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π²ΠΈΠ΄ΠΈ, тСхнологията ADS-B сС Π΅ ΠΏΡ€Π΅Π²ΡŠΡ€Π½Π°Π»Π° Π² интСрСсСн симбиоз, ΠΊΠΎΠ³Π°Ρ‚ΠΎ някакъв стандарт Π΅ ΠΏΠΎΠ»Π΅Π·Π΅Π½ Π½Π΅ само Π½Π° профСсионалиститС, Π½ΠΎ ΠΈ Π½Π° ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΡ‚Π΅ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΠΈ. Но, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π° роля Π² Ρ‚ΠΎΠ²Π° ΠΈΠ·ΠΈΠ³Ρ€Π°Π²Π° намаляванСто Π½Π° Ρ€Π°Π·Ρ…ΠΎΠ΄ΠΈΡ‚Π΅ Π·Π° тСхнологията Π½Π° Ρ†ΠΈΡ„Ρ€ΠΎΠ²ΠΈΡ‚Π΅ SDR-ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΡ†ΠΈ, позволяващи Π½Π° устройството Π±ΡƒΠΊΠ²Π°Π»Π½ΠΎ "Π½Π° ниска Ρ†Π΅Π½Π°" Π΄Π° ΠΏΡ€ΠΈΠ΅ΠΌΠ° сигнали с частота Π½Π°Π΄ Π³ΠΈΠ³Π°Ρ…Π΅Ρ€Ρ†Π°.

Π’ самия стандарт, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, ΠΈΠΌΠ° ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ²Π΅Ρ‡Π΅. Π–Π΅Π»Π°Π΅Ρ‰ΠΈΡ‚Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°Ρ‚ PDF Π½Π° страницата ICAO ΠΈΠ»ΠΈ Π΄Π° посСтят Π²Π΅Ρ‡Π΅ спомСнатия ΠΏΠΎ-Π³ΠΎΡ€Π΅ сайт.

Малко вСроятно Π΅ ΠΌΠ½ΠΎΠ³ΠΎ Ρ…ΠΎΡ€Π° Π΄Π° сС нуТдаят ΠΎΡ‚ всичко написано досСга, Π½ΠΎ ΠΏΠΎΠ½Π΅ основната идСя Π·Π° Ρ‚ΠΎΠ²Π° ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚ΠΈ, надявам сС, остана.

Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚, Π³ΠΎΡ‚ΠΎΠ² Π΄Π΅ΠΊΠΎΠ΄Π΅Ρ€ Π½Π° Python Π²Π΅Ρ‡Π΅ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°, ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΈΠ·ΡƒΡ‡Π΅Π½ Ρ‚ΡƒΠΊ.. А ΠΏΡ€ΠΈΡ‚Π΅ΠΆΠ°Ρ‚Π΅Π»ΠΈΡ‚Π΅ Π½Π° SDR-ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΡ†ΠΈ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° ΡΡŠΠ±Π΅Ρ€Π°Ρ‚ ΠΈ стартират Π³ΠΎΡ‚ΠΎΠ² ADS-B Π΄Π΅ΠΊΠΎΠ΄Π΅Ρ€ ΠΎΡ‚ страницата, Π·Π° ΠΊΠΎΠ΅Ρ‚ΠΎ Π±Π΅ Π³ΠΎΠ²ΠΎΡ€Π΅Π½ΠΎ ΠΏΠΎ-ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ Π² ΠΏΡŠΡ€Π²Π°Ρ‚Π° част.

Π˜Π·Ρ…ΠΎΠ΄Π½ΠΈΡΡ‚ ΠΊΠΎΠ΄ Π½Π° парсСра, описан Π² статията, Π΅ прСдоставСн ΠΏΠΎ-Π΄ΠΎΠ»Ρƒ. Π’ΠΎΠ²Π° Π΅ тСстов ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π½Π΅ ΠΏΡ€Π΅Ρ‚Π΅Π½Π΄ΠΈΡ€Π°Ρ‰ Π·Π° продукция, Π½ΠΎ Π½Π΅Ρ‰ΠΎ Π² Π½Π΅Π³ΠΎ Ρ€Π°Π±ΠΎΡ‚ΠΈ, ΠΈ записаният ΠΏΠΎ-Π³ΠΎΡ€Π΅ Ρ„Π°ΠΉΠ» ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС парсван с Π½Π΅Π³ΠΎ.
Π˜Π·Ρ…ΠΎΠ΄Π΅Π½ ΠΊΠΎΠ΄ (Python)

from __future__ import print_function

from scipy.io import wavfile
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
import math
import sys


def parse_message(data, start, bit_len):
    max_len = bit_len*128
    A = data[start:start + max_len]
    A = signal.resample(A, 10*max_len)
    bits = np.zeros(10*max_len)
    bit_len *= 10
    start_data = bit_len*8

    # Parse first 8 bits
    bits_str = ""
    for p in range(8):
        pos = start_data + bit_len*p
        p1, p2 = A[pos: pos + bit_len/2], A[pos + bit_len/2: pos + bit_len]
        avg1, avg2 = np.average(p1), np.average(p2)
        if avg1 < avg2:
            bits_str += "0"
        elif avg1 > avg2:
            bits_str += "1"

    df = int(bits_str[0:5], 2)

    # Aircraft address (db - https://junzis.com/adb/?q=3b1c5c )
    bits_str = ""
    for p in range(8, 32):
        pos = start_data + bit_len * p
        p1, p2 = A[pos: pos + bit_len / 2], A[pos + bit_len / 2: pos + bit_len]
        avg1, avg2 = np.average(p1), np.average(p2)
        if avg1 < avg2:
            bits_str += "0"
        elif avg1 > avg2:
            bits_str += "1"
    # print "Aircraft address:", bits_str, hex(int(bits_str, 2))
    address = hex(int(bits_str, 2))

    # Filter specific aircraft (optional)
    # if address != "0x3c5ee2":
    #    return

    if df == 16 or df == 17 or df == 18 or df == 19 or df == 20 or df == 21:
        # print "Pos:", start, "DF:", msg_type

        # Data (56bit)
        bits_str = ""
        for p in range(32, 88):
            pos = start_data + bit_len*p
            p1, p2 = A[pos: pos + bit_len/2], A[pos + bit_len/2: pos + bit_len]
            avg1, avg2 = np.average(p1), np.average(p2)
            if avg1 < avg2:
                bits_str += "0"
                # bits[pos + bit_len / 2] = 50
            elif avg1 > avg2:
                bits_str += "1"

        # http://www.lll.lu/~edward/edward/adsb/DecodingADSBposition.html
        # print "Data:"
        # print bits_str[:8], bits_str[8:20],  bits_str[20:22], bits_str[22:22+17], bits_str[39:39+17]
        # Type Code:
        tc, ec = int(bits_str[:5], 2), int(bits_str[5:8], 2)
        # print("DF:", df, "TC:", tc)
        
        # 1 - 4  Aircraft identification
        # 5 - 8  Surface position
        # 9 - 18  Airborne position (w/ Baro Altitude)
        # 19  Airborne velocities

        if tc >= 1 and tc <= 4: # and (df == 17 or df == 18):
            print("Aircraft address:", address)
            print("Data:")
            print(bits_str[:8], bits_str[8:14],  bits_str[14:20], bits_str[20:26], bits_str[26:32], bits_str[32:38], bits_str[38:44])

            symbols = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ#####_###############0123456789######"
            code_str = ""
            for p in range(8):
                c = int(bits_str[8 + 6*p:8 + 6*(p + 1)], 2)
                code_str += symbols[c]
            print("Aircraft Identification:", code_str.replace('#', ''))
            print()
        if tc == 11:
            print("Aircraft address:", address)
            print("Data: (11)")
            print(bits_str[:8], bits_str[8:20],  bits_str[20:22], bits_str[22:22+17], bits_str[39:39+17])

            # Bit 22 contains the F flag which indicates which CPR format is used (odd or even)
            # First frame has F flag = 0 so is even and the second frame has F flag = 1 so odd
            # f = bits_str[21:22]
            # print("F:", int(f, 2))

            # Altitude
            alt1b = bits_str[8:20]
            if alt1b[-5] == '1':
                bits = alt1b[:-5] + alt1b[-4:]
                n = int(bits, 2)
                alt_ft = n*25 - 1000
                print("Alt (ft)", alt_ft)

            # lat_dec = int(bits_str[22:22+17], 2)
            # lon_dec = int(bits_str[39:39+17], 2)
            # print("Lat/Lon:", lat_dec, lon_dec)

            # http://airmetar.main.jp/radio/ADS-B%20Decoding%20Guide.pdf
            print()
        if tc == 19:
            print("Aircraft address:", address)
            print("Data:")
            # print(bits_str)
            print(bits_str[:5], bits_str[5:8], bits_str[8:10], bits_str[10:13], bits_str[13] ,bits_str[14:24], bits_str[24], bits_str[25:35], bits_str[35:36], bits_str[36:65])

            subtype = int(bits_str[5:8], 2)
            # https://mode-s.org/decode/adsb/airborne-velocity.html
            spd, hdg, rocd = -1, -1, -1
            if subtype == 1 or subtype == 2:
                print("Velocity Subtype 1: Ground speed")
            
                v_ew_sign = int(bits_str[13], 2)
                v_ew = int(bits_str[14:24], 2) - 1       # east-west velocity
                
                v_ns_sign = int(bits_str[24], 2)
                v_ns = int(bits_str[25:35], 2) - 1       # north-south velocity
                
                v_we = -1*v_ew if v_ew_sign else v_ew
                v_sn = -1*v_ns if v_ns_sign else v_ns
                
                spd = math.sqrt(v_sn*v_sn + v_we*v_we)  # unit in kts
                
                hdg = math.atan2(v_we, v_sn)
                hdg = math.degrees(hdg)                 # convert to degrees
                hdg = hdg if hdg >= 0 else hdg + 360    # no negative val
            if subtype == 3:
                print("Subtype Subtype 3: Airspeed")
                hdg = int(bits_str[14:24], 2)/1024.0*360.0
                spd = int(bits_str[25:35], 2)
            
            vr_sign = int(bits_str[36], 2)
            vr = int(bits_str[36:45], 2)
            rocd = -1*vr if vr_sign else vr         # rate of climb/descend
            print("Speed (kts):", spd, "Rate:", rocd, "Heading:", hdg)
            print()

        # print()

def calc_coordinates():
    def _cprN(lat, is_odd):
        nl = _cprNL(lat) - is_odd
        return nl if nl > 1 else 1

    def _cprNL(lat):
        try:
            nz = 15
            a = 1 - math.cos(math.pi / (2 * nz))
            b = math.cos(math.pi / 180.0 * abs(lat)) ** 2
            nl = 2 * math.pi / (math.acos(1 - a/b))
            return int(math.floor(nl))
        except:
            # happens when latitude is +/-90 degree
            return 1
    
    def floor_(x):
        return int(math.floor(x))
  
    lat1b, lon1b, alt1b = "10111000111010011", "10000110111111000", "000101111001"
    lat2b, lon2b, alt2b = "10010011101011100", "10000011000011011", "000101110111"
    lat1, lon1, alt1 = int(lat1b, 2), int(lon1b, 2), int(alt1b, 2)
    lat2, lon2, alt2 = int(lat2b, 2), int(lon2b, 2), int(alt2b, 2)
    
    # 131072 is 2^17, since CPR lat and lon are 17 bits each
    cprlat_even, cprlon_even = lat1/131072.0, lon1/131072.0
    cprlat_odd, cprlon_odd = lat2/131072.0, lon2/131072.0
    print(cprlat_even, cprlon_even)

    j = floor_(59*cprlat_even - 60*cprlat_odd)
    print(j)

    air_d_lat_even = 360.0 / 60
    air_d_lat_odd = 360.0 / 59

    # Lat
    lat_even = float(air_d_lat_even * (j % 60 + cprlat_even))
    lat_odd = float(air_d_lat_odd * (j % 59 + cprlat_odd))
    if lat_even >= 270:
        lat_even = lat_even - 360
    if lat_odd >= 270:
        lat_odd = lat_odd - 360

    # Lon
    ni = _cprN(lat_even, 0)
    m = floor_(cprlon_even * (_cprNL(lat_even)-1) - cprlon_odd * _cprNL(lat_even) + 0.5)
    lon = (360.0 / ni) * (m % ni + cprlon_even)
    print("Lat", lat_even, "Lon", lon)

    # Altitude
    # Q-bit (bit 48) indicates whether the altitude is encoded in multiples of 25 or 100 ft (0: 100 ft, 1: 25 ft)
    # The value can represent altitudes from -1000 to +50175 ft.
    if alt1b[-5] == '1':
        bits = alt1b[:-5] + alt1b[-4:]
        n = int(bits, 2)
        alt_ft = n*25 - 1000
        print("Alt (ft)", alt_ft)


fs, data = wavfile.read("adsb_20190311_191728Z_1090000kHz_RF.wav")
T = 1/fs

print("Sample rate %f MS/s" % (fs / 1e6))
print("Cnt samples %d" % len(data))
print("Duration: %f s" % (T * len(data)))

data = data.astype(float)

cnt = data.shape[0]
# Processing only part on file (faster):
# cnt = 10000000
# data = data[:cnt]
print("Processing I/Q...")
I, Q = data[:, 0], data[:, 1]
A = np.sqrt(I*I + Q*Q)

bits = np.zeros(cnt)

# To see scope without any processing, uncomment
# plt.plot(A)
# plt.show()
# sys.exit(0)

print("Extracting signals...")

pos = 0
avg = 200
msg_start = 0
# Find beginning of each signal
while pos < cnt - 16*1024:
    # P1 - message start
    while pos < cnt - 16*1024:
        if A[pos] < avg and A[pos+1] > avg and pos - msg_start > 1000:
            msg_start = pos
            bits[pos] = 100
            pos += 4
            break
        pos += 1

    start1, start2, start3, start4 = msg_start, 0, 0, 0
    # P2
    while pos < cnt - 16*1024:
        if A[pos] < avg and A[pos+1] > avg:
            start2 = pos
            bits[pos] = 90
            pos += 1
            break
        pos += 1
    # P3
    while pos < cnt - 16*1024:
        if A[pos] < avg and A[pos+1] > avg:
            start3 = pos
            bits[pos] = 80
            pos += 1
            break
        pos += 1
    # P4
    while pos < cnt - 16*1024:
        if A[pos] < avg and A[pos+1] > avg:
            start4 = pos
            bits[pos] = 70
            pos += 1
            break
        pos += 1


    sig_diff = start4 - start1
    if 20 < sig_diff < 25:
        bits[msg_start] = 500
        bit_len = int((start4 - start1) / 4.5)
        # print(pos, start1, start4, ' - ', bit_len)
        # start = start1 + 8*bit_len
        parse_message(A, msg_start, bit_len)

        pos += 450

# For debugging: check signal start
# plt.plot(A)
# plt.plot(bits)
# plt.show()

Надявам сС, Ρ‡Π΅ Π½Π° някого ΠΌΡƒ бСшС интСрСсно, благодаря Π·Π° Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅Ρ‚ΠΎ.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster