ΠΠ΄ΡΠ°Π²Π΅ΠΉΡΠ΅, Π₯Π°Π±Ρ. ΠΠ΅ΡΠΎΡΡΠ½ΠΎ Π²ΡΠ΅ΠΊΠΈ, ΠΊΠΎΠΉΡΠΎ Π΅ ΠΈΠ·ΠΏΡΠ°ΡΠ°Π» ΠΈΠ»ΠΈ ΠΏΠΎΡΡΠ΅ΡΠ°Π» ΡΠΎΠ΄Π½ΠΈΠ½ΠΈ ΠΈΠ»ΠΈ ΠΏΡΠΈΡΡΠ΅Π»ΠΈ Π½Π° Π»Π΅ΡΠΈΡΠ΅, Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π» Π±Π΅Π·ΠΏΠ»Π°ΡΠ½ΠΈΡ ΡΠ΅ΡΠ²ΠΈΡ Flightradar24. Π’ΠΎΠ²Π° Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΡΠ΄ΠΎΠ±Π΅Π½ Π½Π°ΡΠΈΠ½ Π·Π° ΠΏΡΠΎΡΠ»Π΅Π΄ΡΠ²Π°Π½Π΅ Π½Π° ΠΌΠ΅ΡΡΠΎΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ Π½Π° ΡΠ°ΠΌΠΎΠ»Π΅ΡΠ° Π² ΡΠ΅Π°Π»Π½ΠΎ Π²ΡΠ΅ΠΌΠ΅.

Π Π±Π΅ΡΠ΅ ΠΎΠΏΠΈΡΠ°Π½ ΠΏΡΠΈΠ½ΡΠΈΠΏΡΡ Π½Π° ΡΠ°Π±ΠΎΡΠ° Π½Π° ΡΠ°ΠΊΡΠ² ΠΎΠ½Π»Π°ΠΉΠ½ ΡΠ΅ΡΠ²ΠΈΡ. Π‘Π΅Π³Π° ΡΠ΅ ΠΏΡΠΎΠ΄ΡΠ»ΠΆΠΈΠΌ ΠΈ ΡΠ΅ ΡΠ°Π·Π±Π΅ΡΠ΅ΠΌ ΠΊΠ°ΠΊΠ²ΠΈ Π΄Π°Π½Π½ΠΈ ΡΠ΅ ΠΏΡΠ΅Π΄Π°Π²Π°Ρ ΠΈ ΠΏΡΠΈΠ΅ΠΌΠ°Ρ ΠΎΡ Π²ΡΠ·Π΄ΡΡ
ΠΎΠΏΠ»Π°Π²Π°ΡΠ΅Π»Π½ΠΎΡΠΎ ΡΡΠ΅Π΄ΡΡΠ²ΠΎ Π΄ΠΎ ΠΏΡΠΈΠ΅ΠΌΠ½Π°ΡΠ° ΡΡΠ°Π½ΡΠΈΡ, ΠΈ ΡΠ΅ Π³ΠΈ Π΄Π΅ΠΊΠΎΠ΄ΠΈΡΠ°ΠΌΠ΅ ΡΠ°ΠΌΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΠ° Π½Π° Python.
ΠΡΡΠΎΡΠΈΡ
ΠΡΠ΅Π²ΠΈΠ΄Π½ΠΎ Π΅, ΡΠ΅ Π΄Π°Π½Π½ΠΈΡΠ΅ Π·Π° ΡΠ°ΠΌΠΎΠ»Π΅ΡΠΈΡΠ΅ Π½Π΅ ΡΠ΅ ΠΏΡΠ΅Π΄Π°Π²Π°Ρ, Π·Π° Π΄Π° ΠΌΠΎΠ³Π°Ρ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈΡΠ΅ Π΄Π° Π³ΠΈ Π²ΠΈΠΆΠ΄Π°Ρ Π½Π° ΡΠΌΠ°ΡΡΡΠΎΠ½ΠΈΡΠ΅ ΡΠΈ. Π‘ΠΈΡΡΠ΅ΠΌΠ°ΡΠ° ΡΠ΅ Π½Π°ΡΠΈΡΠ° ADSβB (Automatic dependent surveillanceβbroadcast) ΠΈ ΡΠ»ΡΠΆΠΈ Π·Π° Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ½ΠΎ ΠΏΡΠ΅Π΄Π°Π²Π°Π½Π΅ Π½Π° ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ Π·Π° Π²ΡΠ·Π΄ΡΡ ΠΎΠΏΠ»Π°Π²Π°ΡΠ΅Π»Π½ΠΎΡΠΎ ΡΡΠ΅Π΄ΡΡΠ²ΠΎ Π² Π΄ΠΈΡΠΏΠ΅ΡΡΠ΅ΡΡΠΊΠΈΡ ΡΠ΅Π½ΡΡΡ β ΠΏΡΠ΅Π΄Π°Π²Π°Ρ ΡΠ΅ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ, ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈ, ΠΏΠΎΡΠΎΠΊΠ°, ΡΠΊΠΎΡΠΎΡΡ, Π²ΠΈΡΠΎΡΠΈΠ½Π° ΠΈ Π΄ΡΡΠ³ΠΈ Π΄Π°Π½Π½ΠΈ. ΠΡΠ΅Π΄ΠΈ ΠΏΠΎΡΠ²Π°ΡΠ° Π½Π° ΡΠ°ΠΊΠΈΠ²Π° ΡΠΈΡΡΠ΅ΠΌΠΈ, Π΄ΠΈΡΠΏΠ΅ΡΡΠ΅ΡΡΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π²ΠΈΠΆΠ΄Π° ΡΠ°ΠΌΠΎ ΡΠΎΡΠΊΠ° Π½Π° ΡΠ°Π΄Π°ΡΠ°. Π’ΠΎΠ²Π° ΡΡΠ°Π½Π° Π½Π΅Π΄ΠΎΡΡΠ°ΡΡΡΠ½ΠΎ, ΠΊΠΎΠ³Π°ΡΠΎ ΡΠ°ΠΌΠΎΠ»Π΅ΡΠΈΡΠ΅ ΡΡΠ°Π½Π°Ρ Π° ΡΠ²ΡΡΠ΄Π΅ ΠΌΠ½ΠΎΠ³ΠΎ.
Π’Π΅Ρ Π½ΠΈΡΠ΅ΡΠΊΠΈ, ADS-B ΡΠ΅ ΡΡΡΡΠΎΠΈ ΠΎΡ ΠΏΡΠ΅Π΄Π°Π²Π°ΡΠ΅Π» Π½Π° Π²ΡΠ·Π΄ΡΡ ΠΎΠΏΠ»Π°Π²Π°ΡΠ΅Π»Π½ΠΎΡΠΎ ΡΡΠ΅Π΄ΡΡΠ²ΠΎ, ΠΊΠΎΠΉΡΠΎ ΠΏΠ΅ΡΠΈΠΎΠ΄ΠΈΡΠ½ΠΎ ΠΈΠ·ΠΏΡΠ°ΡΠ° ΠΏΠ°ΠΊΠ΅ΡΠΈ Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ Π½Π° Π΄ΠΎΡΡΠ°ΡΡΡΠ½ΠΎ Π²ΠΈΡΠΎΠΊΠ° ΡΠ΅ΡΡΠΎΡΠ° ΠΎΡ 1090 ΠΠΡ (ΠΈΠΌΠ° ΠΈ Π΄ΡΡΠ³ΠΈ ΡΠ΅ΠΆΠΈΠΌΠΈ, Π½ΠΎ ΡΠ΅ Π½Π΅ Π½ΠΈ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΡΠ²Π°Ρ, ΡΡΠΉ ΠΊΠ°ΡΠΎ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈΡΠ΅ ΡΠ΅ ΠΏΡΠ΅Π΄Π°Π²Π°Ρ ΡΠ°ΠΌΠΎ ΡΡΠΊ). Π Π°Π·Π±ΠΈΡΠ° ΡΠ΅, ΠΎΡΠ²Π΅Π½ ΠΏΡΠ΅Π΄Π°Π²Π°ΡΠ΅Π»Ρ, ΠΈΠΌΠ° ΠΈ ΠΏΡΠΈΠ΅ΠΌΠ½ΠΈΠΊ Π½ΡΠΊΡΠ΄Π΅ Π½Π° Π»Π΅ΡΠΈΡΠ΅ΡΠΎ, Π½ΠΎ Π·Π° Π½Π°Ρ, ΠΊΠ°ΡΠΎ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈ, ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ΅Π½ Π΅ Π½Π°ΡΠΈΡΡ ΡΠΎΠ±ΡΡΠ²Π΅Π½ ΠΏΡΠΈΠ΅ΠΌΠ½ΠΈΠΊ.
ΠΠ° ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅, ΠΏΡΡΠ²Π°ΡΠ° ΡΠ°ΠΊΠ°Π²Π° ΡΠΈΡΡΠ΅ΠΌΠ°, Airnav Radarbox, ΠΏΡΠ΅Π΄Π½Π°Π·Π½Π°ΡΠ΅Π½Π° Π·Π° ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈ, ΡΠ΅ ΠΏΠΎΡΠ²ΠΈ ΠΏΡΠ΅Π· 2007 Π³ΠΎΠ΄ΠΈΠ½Π° ΠΈ ΡΡΡΡΠ²Π°ΡΠ΅ ΠΎΠΊΠΎΠ»ΠΎ 900$, Π° ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠ°ΡΠ° Π·Π° ΠΌΡΠ΅ΠΆΠΎΠ²ΠΈ ΡΡΠ»ΡΠ³ΠΈ Π±Π΅ΡΠ΅ ΠΎΠΊΠΎΠ»ΠΎ 250$ Π½Π° Π³ΠΎΠ΄ΠΈΠ½Π°.

ΠΡΠ·ΠΈΠ²ΠΈ Π½Π° ΠΏΡΡΠ²ΠΈΡΠ΅ ΡΡΡΠΊΠΈ ΡΠΎΠ±ΡΡΠ²Π΅Π½ΠΈΡΠΈ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΏΡΠΎΡΠ΅ΡΠ΅ΡΠ΅ Π½Π° ΡΠΎΡΡΠΌΠ° . Π‘Π΅Π³Π°, ΠΊΠΎΠ³Π°ΡΠΎ ΠΌΠ°ΡΠΎΠ²ΠΎ ΡΠ΅ ΠΏΠΎΡΠ²ΠΈΡ
Π° RTL-SDR ΠΏΡΠΈΠ΅ΠΌΠ½ΠΈΡΠΈ, Π°Π½Π°Π»ΠΎΠ³ΠΈΡΠ½ΠΎ ΡΡΡΡΠΎΠΉΡΡΠ²ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΡΡΠ±Π΅ΡΠ΅ Π·Π° 30$, ΠΏΠΎ-ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ Π·Π° ΡΠΎΠ²Π° Π±Π΅ΡΠ΅ Π² . ΠΠΈΠ΅ ΠΎΠ±Π°ΡΠ΅ ΡΠ΅ ΠΏΡΠ΅ΠΌΠΈΠ½Π΅ΠΌ Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΎ ΠΊΡΠΌ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π° β Π½Π΅ΠΊΠ° Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊ ΡΠ°Π±ΠΎΡΠΈ.
ΠΡΠΈΠ΅ΠΌ Π½Π° ΡΠΈΠ³Π½Π°Π»ΠΈ
ΠΡΡΠ²ΠΎ, ΡΠΈΠ³Π½Π°Π»ΡΡ ΡΡΡΠ±Π²Π° Π΄Π° Π±ΡΠ΄Π΅ Π·Π°ΠΏΠΈΡΠ°Π½. Π¦Π΅Π»ΠΈΡΡ ΡΠΈΠ³Π½Π°Π» ΠΈΠΌΠ° ΠΏΡΠΎΠ΄ΡΠ»ΠΆΠΈΡΠ΅Π»Π½ΠΎΡΡ ΡΠ°ΠΌΠΎ 120 ΠΌΠΈΠΊΡΠΎΡΠ΅ΠΊΡΠ½Π΄ΠΈ, Π·Π°ΡΠΎΠ²Π° Π·Π° ΠΊΠΎΠΌΡΠΎΡΡΠ½ΠΎ ΡΠ°Π·ΡΡΠ½ΡΠ²Π°Π½Π΅ Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΈΡΠ΅ ΠΌΡ, ΠΆΠ΅Π»Π°ΡΠ΅Π»Π΅Π½ Π΅ SDR ΠΏΡΠΈΠ΅ΠΌΠ½ΠΈΠΊ Ρ ΡΠ΅ΡΡΠΎΡΠ° Π½Π° Π΄ΠΈΡΠΊΡΠ΅ΡΠΈΠ·Π°ΡΠΈΡ Π½Π΅ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠ° ΠΎΡ 5 MHz.

Π‘Π»Π΅Π΄ Π·Π°ΠΏΠΈΡΠ²Π°Π½Π΅ ΠΏΠΎΠ»ΡΡΠ°Π²Π°ΠΌΠ΅ 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()
Π Π΅Π·ΡΠ»ΡΠ°Ρ: Π²ΠΈΠΆΠ΄Π°ΠΌΠ΅ ΡΡΠ½ΠΈ Β«ΠΈΠΌΠΏΡΠ»ΡΠΈΒ» Π½Π° ΡΠΎΠ½Π° Π½Π° ΡΡΠΌΠ°.

ΠΡΠ΅ΠΊΠΈ Β«ΠΈΠΌΠΏΡΠ»ΡΒ» Π΅ ΠΈΠΌΠ΅Π½Π½ΠΎ ΡΠΈΠ³Π½Π°Π», ΡΡΡΡΠΊΡΡΡΠ°ΡΠ° Π½Π° ΠΊΠΎΠΉΡΠΎ Π΅ Π΄ΠΎΠ±ΡΠ΅ Π²ΠΈΠ΄ΠΈΠΌΠ°, Π°ΠΊΠΎ ΡΠ²Π΅Π»ΠΈΡΠΈΠΌ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ΡΠΎ Π½Π° Π³ΡΠ°ΡΠΈΠΊΠ°ΡΠ°.

ΠΠ°ΠΊΡΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π²ΠΈΠ΄ΠΈΠΌ, ΠΊΠ°ΡΡΠΈΠ½ΠΊΠ°ΡΠ° Π½Π°ΠΏΡΠ»Π½ΠΎ ΡΡΠΎΡΠ²Π΅ΡΡΡΠ²Π° Π½Π° ΠΎΠΏΠΈΡΠ°Π½ΠΎΡΠΎ ΠΏΠΎ-Π³ΠΎΡΠ΅. ΠΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΡΠ΅ΠΌΠΈΠ½Π΅ΠΌ ΠΊΡΠΌ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° Π½Π° Π΄Π°Π½Π½ΠΈΡΠ΅.
ΠΠ΅ΠΊΠΎΠ΄ΠΈΡΠ°Π½Π΅
ΠΡΡΠ²ΠΎ, ΡΡΡΠ±Π²Π° Π΄Π° ΠΏΠΎΠ»ΡΡΠΈΠΌ Π±ΠΈΡΠΎΠ²ΠΈΡ ΠΏΠΎΡΠΎΠΊ. Π‘Π°ΠΌΠΈΡΡ ΡΠΈΠ³Π½Π°Π» Π΅ Π·Π°ΠΊΠΎΠ΄ΠΈΡΠ°Π½ Ρ ΠΏΠΎΠΌΠΎΡΡΠ° Π½Π° manchester encoding:

ΠΡ ΡΠ°Π·Π»ΠΈΠΊΠ°ΡΠ° Π½Π° Π½ΠΈΠ²Π°ΡΠ° Π² ΠΏΠΎΠ»ΡΠ±Π°ΠΉΡΠΈΡΠ΅ Π»Π΅ΡΠ½ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΠΎΠ»ΡΡΠΈΠΌ ΡΠ΅Π°Π»Π½ΠΈ Β«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"
Π‘ΡΡΡΠΊΡΡΡΠ° Π½Π° ΡΠ°ΠΌΠΈΡ ΡΠΈΠ³Π½Π°Π» ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΠΏΠΎ ΡΠ»Π΅Π΄Π½ΠΈΡ Π½Π°ΡΠΈΠ½:

ΠΠ΅ΠΊΠ° ΡΠ°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΏΠΎΠ»Π΅ΡΠ°ΡΠ° ΠΏΠΎ-ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ.
DF (Downlink Format, 5 Π±ΠΈΡΠ°) β ΠΎΠΏΡΠ΅Π΄Π΅Π»Ρ ΡΠΈΠΏΠ° Π½Π° ΡΡΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ΡΠΎ. ΠΠΌΠ° Π½ΡΠΊΠΎΠ»ΠΊΠΎ ΡΠΈΠΏΠ°:

()
ΠΠ½ΡΠ΅ΡΠ΅ΡΡΠ²Π° Π½ΠΈ ΡΠ°ΠΌΠΎ ΡΠΈΠΏ DF17, ΡΡΠΉ ΠΊΠ°ΡΠΎ ΠΈΠΌΠ΅Π½Π½ΠΎ ΡΠΎΠΉ ΡΡΠ΄ΡΡΠΆΠ° ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈΡΠ΅ Π½Π° Π²ΡΠ·Π΄ΡΡΠ½ΠΎΡΠΎ ΡΡΠ΄Π½ΠΎ.
ICAO (24 Π±ΠΈΡΠ°) β ΠΌΠ΅ΠΆΠ΄ΡΠ½Π°ΡΠΎΠ΄Π΅Π½ ΡΠ½ΠΈΠΊΠ°Π»Π΅Π½ ΠΊΠΎΠ΄ Π½Π° Π²ΡΠ·Π΄ΡΡΠ½ΠΎΡΠΎ ΡΡΠ΄Π½ΠΎ. ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΏΡΠΎΠ²Π΅ΡΠΈΡΠ΅ ΡΠ°ΠΌΠΎΠ»Π΅ΡΠ° ΠΏΠΎ Π½Π΅Π³ΠΎΠ²ΠΈΡ ΠΊΠΎΠ΄ Π½Π° (Π·Π° ΡΡΠΆΠ°Π»Π΅Π½ΠΈΠ΅, Π°Π²ΡΠΎΡΡΡ Π΅ ΡΠΏΡΡΠ» Π΄Π° Π°ΠΊΡΡΠ°Π»ΠΈΠ·ΠΈΡΠ° Π±Π°Π·Π°ΡΠ°, Π½ΠΎ ΡΡ Π²ΡΠ΅ ΠΎΡΠ΅ Π΅ Π°ΠΊΡΡΠ°Π»Π½Π°). ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π·Π° ΠΊΠΎΠ΄ 3c5ee2 ΠΈΠΌΠ°ΠΌΠ΅ ΡΠ»Π΅Π΄Π½Π°ΡΠ° ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ:

ΠΠΎΡΠ΅ΠΊΡΠΈΡ: Π² ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ΡΠΎ Π½Π° ΠΊΠΎΠ΄Π° ICAO Π΅ ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½ΠΎ ΠΏΠΎ-ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ, ΠΈΠ½ΡΠ΅ΡΠ΅ΡΡΠ²Π°ΡΠΈΡΠ΅ ΡΠ΅ ΠΏΡΠ΅ΠΏΠΎΡΡΡΠ²Π°ΠΌ Π΄Π° ΡΠ΅ Π·Π°ΠΏΠΎΠ·Π½Π°ΡΡ.
ΠΠΠΠ (56 ΠΈΠ»ΠΈ 112 Π±ΠΈΡΠ°) β ΡΠ°ΠΌΠΈΡΠ΅ Π΄Π°Π½Π½ΠΈ, ΠΊΠΎΠΈΡΠΎ ΡΠ΅ Π΄Π΅ΠΊΠΎΠ΄ΠΈΡΠ°ΠΌΠ΅. ΠΡΡΠ²ΠΈΡΠ΅ 5 Π±ΠΈΡΠ° ΠΎΡ Π΄Π°Π½Π½ΠΈΡΠ΅ β ΠΏΠΎΠ»Π΅ Type Code, ΡΡΠ΄ΡΡΠΆΠ°ΡΠΎ ΠΏΠΎΠ΄ΡΠΈΠΏ Π½Π° ΡΡΡ ΡΠ°Π½ΡΠ²Π°Π½ΠΈΡΠ΅ Π΄Π°Π½Π½ΠΈ (Π΄Π° Π½Π΅ ΡΠ΅ Π±ΡΡΠΊΠ° Ρ DF). Π’Π°ΠΊΠΈΠ²Π° ΡΠΈΠΏΠΎΠ²Π΅ ΠΈΠΌΠ° Π΄ΠΎΡΡΠ°:

()
ΠΠ΅ΠΊΠ° ΡΠ°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Π½ΡΠΊΠΎΠ»ΠΊΠΎ ΠΏΡΠΈΠΌΠ΅ΡΠ° Π½Π° ΠΏΠ°ΠΊΠ΅ΡΠΈ.
ΠΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ Π½Π° Π²ΡΠ·Π΄ΡΡΠ½ΠΎ ΡΡΠ΄Π½ΠΎ
ΠΡΠΈΠΌΠ΅Ρ Π² Π±ΠΈΠ½Π°ΡΠ΅Π½ Π²ΠΈΠ΄:
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.

ΠΡΠΈΠΌΠ΅Ρ Π·Π° ΡΠ΅ΡΠ½ΠΈ ΠΈ Π½Π΅ΡΠ΅ΡΠ½ΠΈ ΠΏΠ°ΠΊΠ΅ΡΠΈ:
01011 000 000101110110 00 10111000111001000 10000110101111001
01011 000 000110010000 01 10010011110000110 10000011110001000
Π‘Π°ΠΌΠΎΡΠΎ ΠΈΠ·ΡΠΈΡΠ»Π΅Π½ΠΈΠ΅ Π½Π° ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈΡΠ΅ ΡΠ΅ ΡΠ»ΡΡΠ²Π° ΠΏΠΎ Π΄ΠΎΡΡΠ° ΡΠ»ΠΎΠΆΠ½Π° ΡΠΎΡΠΌΡΠ»Π°:

()
ΠΠ΅ ΡΡΠΌ ΡΠΏΠ΅ΡΠΈΠ°Π»ΠΈΡΡ ΠΏΠΎ ΠΠΠ‘, ΡΠ°ΠΊΠ° ΡΠ΅ ΠΎΡΠΊΡΠ΄Π΅ ΡΠ΅ ΠΈΠ·Π²Π΅ΠΆΠ΄Π°, Π½Π΅ Π·Π½Π°ΠΌ. ΠΠΊΠΎ Π½ΡΠΊΠΎΠΉ Π·Π½Π°Π΅, ΠΌΠΎΠ»Ρ ΠΏΠΈΡΠ΅ΡΠ΅ Π² ΠΊΠΎΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ΅.
ΠΠΈΡΠΎΡΠΈΠ½Π°ΡΠ° ΡΠ΅ ΠΈΠ·ΡΠΈΡΠ»ΡΠ²Π° ΠΏΠΎ-Π»Π΅ΡΠ½ΠΎ β Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡ ΠΎΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ Π±ΠΈΡ, ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΡΠ΄Π΅ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π΅Π½Π° ΠΈΠ»ΠΈ ΠΊΡΠ°ΡΠ½Π° Π½Π° 25, ΠΈΠ»ΠΈ Π½Π° 100 ΡΡΡΠ°.
ΠΡΠ·Π΄ΡΡΠ½Π° ΡΠΊΠΎΡΠΎΡΡ
ΠΠ°ΠΊΠ΅Ρ Ρ TC=19. ΠΠ½ΡΠ΅ΡΠ΅ΡΠ½ΠΎ Π΅, ΡΠ΅ ΡΠΊΠΎΡΠΎΡΡΡΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΡΠ΄Π΅ ΠΊΠ°ΠΊΡΠΎ ΡΠΎΡΠ½Π°, ΡΠΏΡΡΠΌΠΎ Π·Π΅ΠΌΡΡΠ° (Ground Speed), ΡΠ°ΠΊΠ° ΠΈ Π²ΡΠ·Π΄ΡΡΠ½Π°, ΠΈΠ·ΠΌΠ΅ΡΠ²Π°Π½Π° ΠΎΡ Π΄Π°ΡΡΠΈΠΊΠ° Π½Π° ΡΠ°ΠΌΠΎΠ»Π΅ΡΠ° (Airspeed). ΠΡΠ΅Π΄Π°Π²Π°Ρ ΡΠ΅ ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΠΏΠΎΠ»Π΅ΡΠ°:

()
ΠΠ°ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅
ΠΠ°ΠΊΡΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π²ΠΈΠ΄ΠΈ, ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΡΡΠ° ADS-B ΡΠ΅ Π΅ ΠΏΡΠ΅Π²ΡΡΠ½Π°Π»Π° Π² ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ΅Π½ ΡΠΈΠΌΠ±ΠΈΠΎΠ·, ΠΊΠΎΠ³Π°ΡΠΎ Π½ΡΠΊΠ°ΠΊΡΠ² ΡΡΠ°Π½Π΄Π°ΡΡ Π΅ ΠΏΠΎΠ»Π΅Π·Π΅Π½ Π½Π΅ ΡΠ°ΠΌΠΎ Π½Π° ΠΏΡΠΎΡΠ΅ΡΠΈΠΎΠ½Π°Π»ΠΈΡΡΠΈΡΠ΅, Π½ΠΎ ΠΈ Π½Π° ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΡΠ΅ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈ. ΠΠΎ, ΡΠ°Π·Π±ΠΈΡΠ° ΡΠ΅, ΠΊΠ»ΡΡΠΎΠ²Π° ΡΠΎΠ»Ρ Π² ΡΠΎΠ²Π° ΠΈΠ·ΠΈΠ³ΡΠ°Π²Π° Π½Π°ΠΌΠ°Π»ΡΠ²Π°Π½Π΅ΡΠΎ Π½Π° ΡΠ°Π·Ρ ΠΎΠ΄ΠΈΡΠ΅ Π·Π° ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΡΡΠ° Π½Π° ΡΠΈΡΡΠΎΠ²ΠΈΡΠ΅ SDR-ΠΏΡΠΈΠ΅ΠΌΠ½ΠΈΡΠΈ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ²Π°ΡΠΈ Π½Π° ΡΡΡΡΠΎΠΉΡΡΠ²ΠΎΡΠΎ Π±ΡΠΊΠ²Π°Π»Π½ΠΎ "Π½Π° Π½ΠΈΡΠΊΠ° ΡΠ΅Π½Π°" Π΄Π° ΠΏΡΠΈΠ΅ΠΌΠ° ΡΠΈΠ³Π½Π°Π»ΠΈ Ρ ΡΠ°ΡΡΠΎΡΠ° Π½Π°Π΄ Π³ΠΈΠ³Π°Ρ Π΅ΡΡΠ°.
Π ΡΠ°ΠΌΠΈΡ ΡΡΠ°Π½Π΄Π°ΡΡ, ΡΠ°Π·Π±ΠΈΡΠ° ΡΠ΅, ΠΈΠΌΠ° ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ²Π΅ΡΠ΅. ΠΠ΅Π»Π°Π΅ΡΠΈΡΠ΅ ΠΌΠΎΠ³Π°Ρ Π΄Π° ΡΠ°Π·Π³Π»Π΅Π΄Π°Ρ PDF Π½Π° ΡΡΡΠ°Π½ΠΈΡΠ°ΡΠ° ΠΈΠ»ΠΈ Π΄Π° ΠΏΠΎΡΠ΅ΡΡΡ Π²Π΅ΡΠ΅ ΡΠΏΠΎΠΌΠ΅Π½Π°ΡΠΈΡ ΠΏΠΎ-Π³ΠΎΡΠ΅ .
ΠΠ°Π»ΠΊΠΎ Π²Π΅ΡΠΎΡΡΠ½ΠΎ Π΅ ΠΌΠ½ΠΎΠ³ΠΎ Ρ ΠΎΡΠ° Π΄Π° ΡΠ΅ Π½ΡΠΆΠ΄Π°ΡΡ ΠΎΡ Π²ΡΠΈΡΠΊΠΎ Π½Π°ΠΏΠΈΡΠ°Π½ΠΎ Π΄ΠΎΡΠ΅Π³Π°, Π½ΠΎ ΠΏΠΎΠ½Π΅ ΠΎΡΠ½ΠΎΠ²Π½Π°ΡΠ° ΠΈΠ΄Π΅Ρ Π·Π° ΡΠΎΠ²Π° ΠΊΠ°ΠΊ ΡΠ°Π±ΠΎΡΠΈ, Π½Π°Π΄ΡΠ²Π°ΠΌ ΡΠ΅, ΠΎΡΡΠ°Π½Π°.
ΠΡΡΡΠ½ΠΎΡΡ, Π³ΠΎΡΠΎΠ² Π΄Π΅ΠΊΠΎΠ΄Π΅Ρ Π½Π° 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
