áááşášáááŹá፠Habrá ááąááŹááşááąáŤáşáážá áá˝áąááťááŻá¸ááťáŹá¸ áááŻáˇáááŻááş áá°áááşááťááşá¸ááťáŹá¸áážááˇáş áá˝áąáˇááŻáśáá°á¸áá° áááŻáˇáááŻááş ááźááşáá°á¸áá°áááŻááşá¸ áĄááá˛áˇáááşááąáŹááşáážáŻ Flightradar24 ááᯠáĄááŻáśá¸ááźáŻáá°á¸ááźááąáááşá á¤áááşáážáŹ ááąááŹááşá áááşááąááŹááᯠáĄááťáááşáážááˇáşáááźáąá¸áᎠááźáąááŹááśáááş áĄáá˝ááşáĄáááşááźáąááąáŹ áááşá¸áááşá¸ááźá áşáááşá

Đ áááŻáá˛áˇáááŻáˇááąáŹáĄá˝ááşáááŻááşá¸áááşááąáŹááşáážáŻááááşáááşáážáŻááááŹááááŻááąáŹáşááźáá˛áˇáááşá áááŻááťá˝ááşáŻááşáááŻáˇ áááşááśáá˝áŹá¸á ááąááŹááşááž áááşááśááąá¸ááŹááááŻáˇ áááŻáˇáá˝ážááşáááˇáş ááąááŹááťáŹá¸ááᯠáážáŹáá˝áąááźáŽá¸ Python ááᯠáĄááŻáśá¸ááźáŻá áááşá¸áááŻáˇááᯠáááŻááşáááŻááşááŻááşááŻááşááŤáááşá
ááŻáśááźááş
áááşáážáŹá¸áááşáážáŹá áĄááŻáśá¸ááźáŻáá°ááťáŹá¸áááş áááşá¸áááŻáˇáá áááşááŻááşá¸ááťáŹá¸áá˝ááş áááşá¸áááŻááźááşáááŻááşá áąáááşáĄáá˝ááş ááąááŹááşáážááˇáşáááşáááşáááˇáş ááąááŹááťáŹá¸ááᯠááá°á¸á ááşáááŻááşááąá áĄáááŻááŤá áá áşááᯠADS-B (áĄáááŻáĄááťáąáŹááşáážáŽáááŻá áąáŹááˇáşááźááˇáşááąá¸-ááŻááşáá˝ážááˇáşáážáŻ) ááŻááąáŤáşááźáŽá¸ áááşá¸áááş ááąááŹááşáážááˇáşáááşáááşááąáŹ áĄááťááşáĄáááşááťáŹá¸ááᯠááááşá¸ááťáŻááşááąá¸á ááşááŹáááŻáˇ áĄáááŻáĄááťáąáŹááş áááŻáˇáá˝ážááşáááşáĄáá˝ááş áĄááŻáśá¸ááźáŻáááş - áááşá¸á identifier, coordinates, direction, speed, altitude áážááˇáş áĄááźáŹá¸ááąáŹ data ááťáŹá¸ááᯠááąá¸áááŻáˇááŤáááşá ááááşá áááşá¸á áá áşááťáŹá¸ áááąáŤáşááŽáá˝ááş á áąáá˝ážááşáá°áááş ááąááŤááąáŤáşáá˝ááş áĄá ááşáá áşá ááşáᏠááźááşáááŻááşáá˛áˇáááşá ááąááŹááşáá˝áą áĄáááşá¸ááťáŹá¸ááŹáá˛áˇáĄá፠ááŤá áááŻáśááąáŹááşáá°á¸á
áááşá¸áááŹáááŻááşá¸áĄáá ADS-B áá˝ááş 1090 MHz ááźááˇáşááŹá¸ááąáŹááźáááşáážáŻááşá¸ááźááˇáş áĄááťááşáĄáááşááŻááşáááŻá¸áážáŻááťáŹá¸ááᯠáĄááŤáĄáŹá¸ááťáąáŹáşá á˝áŹ ááąá¸áááŻáˇáááˇáş ááąááŹááşááąáŤáşáá˝ááş ááŻááşáá˝ážááˇáşáááˇáşááááááŹáá áşááŻááŤáážááááş (áĄááźáŹá¸ááŻááşááťáŹá¸áážááááşá áááŻáˇááąáŹáş áááşá¸áááŻáˇááᯠá¤ááąááŹáá˝ááşáᏠáááŻáˇáá˝ážááşááąáŹááźáąáŹááˇáş ááťá˝ááşáŻááşáááŻáˇ ááááşá áááşááááşá áŹá¸ááŤ)á ááŻááşááŤáááş, transmitter áĄááźááşá ááąááááşáážáŹ receiver áááşá¸áážááááşá ááŤááąáááˇáş ááŻáśá¸á á˝á˛áá°áá˝áąáĄáá˝ááşááąáŹáˇ á áááşáááşá áŹá¸á ááŹááąáŹááşá¸áá˛áˇ receiver á ááťá˝ááşááąáŹáşáááŻáˇáááŻááşáááŻááşááŤáá˛á
á ááŹá¸áá ááşá áážááŻááşá¸áážááşááźááˇáşáááşá ááŹáááşáĄááŻáśá¸ááźáŻáá°ááťáŹá¸áĄáá˝ááş ááŽáááŻááşá¸ááŻááşááŹá¸ááąáŹ áááááŻáśá¸ Airnav Radarbox á áá áşáááş áááá ááŻáážá áşáá˝ááş ááąáŤáşáá˝ááşááŹáá˛áˇááźáŽá¸ ááąáŤáşáᏠááá áááˇáş ááŻááşááťáá˛áˇáááşá 250$ áá˝ááşáááşáááşááąáŹááşáážáŻááťáŹá¸áĄáá˝ááş á áŹáááşá¸áá˝ááşá¸á áá áşáážá áşááťážááş ááŻááşááťá ááááşá

áááááŻáśá¸ ááŻáážáŹá¸áááŻááşáážááşááťáŹá¸ááśááž ááŻáśá¸áááşááťááşááťáŹá¸ááᯠáááŻáááşáá˝ááş áááşáážáŻáááŻááşááŤáááşá . ááᯠRTL-SDR áááşááśááááááŹááťáŹá¸ááᯠáá˝ááşááťááşá
á˝áŹááážááááŻááşááźáŽááźá
áşááąáŹááźáąáŹááˇáş áĄááŹá¸áá°ááááááŹááᯠ$30 ááźááˇáş áááşáááşáááŻááşáááşá áááşá¸áážááˇáşáááşáááşáááˇáş ááąáŹááşáááşáĄááąá¸á
áááşáĄááťááşáĄáááşááťáŹá¸ááᯠááąáŹáşááźááŹá¸áááş . ááááŻáááŻááąáŹááşáááŻáˇ áááşáá˝áŹá¸ááźááŤá
ááŻáˇ - áááşá¸áááş áááşáááŻáˇáĄááŻááşááŻááşáááşááᯠááźááˇáşááźááŤá
ááŻáˇá
áĄááťááşááźáážáŻááťáŹá¸ááᯠáááşááśááźááşá¸á
ááááŚá¸á á˝áŹ signal áááŻáážááşáááşá¸áááşáááşáááŻáĄááşáááşá áĄááťááşááźáážáŻáá áşááŻááŻáśá¸áááş 120 áááŻááşááááŻá áášáááˇáşááťážáᏠáážááşááťáŹá¸ááąáŹááźáąáŹááˇáş áááşá¸ááĄá áááşáĄáááŻááşá¸ááťáŹá¸ááᯠáá˝á˛ááźááşá¸á áááşááźáŹáááş áĄáááşá¸ááŻáśá¸ 5 MHz ááá°ááŹááźáááşáážáŻááşá¸áážáááąáŹ SDR áááşááśáá°áááş áážá áşáááŻáá˝ááşááąáŹááşá¸áááşá

áážááşáááşá¸áááşááźáŽá¸ááąáŹááşá ááťá˝ááşáŻááşáááŻáˇáááş ááá°ááŹááźáááşáážáŻááşá¸ 5000000 ááá°ááŹ/sec ááźááˇáş WAV áááŻááşááᯠááážááááşá áááŻáá˛áˇáááŻáˇááąáŹ áĄááśáá˝ááşá¸áážáŻá á
áášáááˇáş 30 ááźáŹ "áĄááąá¸ááťáááş" 500 MB áááˇáşáážááááşá ááŻááşááŤáááşá ááŽááŽááŹáááąááŹáá˛áˇ ááŹá¸ááąáŹááşááŹá áĄááŻáśá¸ááááşááŤáá°á¸ - áááŻááşáážáŹ áĄááśáááŤáááşááąáááˇáş áááŻááşáááŻááş áá
áşááťá
áşáááşááąááŽááᯠáĄááťááşááźáážáŻ - ááŤá 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()
ááááş- ááąáŹááşááśáá°ááśááśááᯠáááˇáşááťááşáááˇáş ááźááşááŹá¸ááąáŹ "áá˛áˇááťáŹá¸" ááᯠááťá˝ááşáŻááşáááŻáˇ ááźááşáááşá

"áá˝áąá¸ááŻááşáážáŻááşá¸" áá
áşááŻá
áŽáááş ááááşáá
áşááąáŤáşáážá ááźááşáááşááźááşááŹá¸áážáŻááᯠáááŻá¸ááźážááˇáşááŤá áááşá¸áá˝á˛áˇá
ááşá¸ááŻáśáááş áážááşá¸áááşá¸á
á˝áŹááźááşáááŻááşáááşá

áááşáá˝áąáˇááźááşááááˇáşáĄáááŻááşá¸á ááŻáśáááş áĄáááşááąáŹáşááźááťááşáá˝ááşááąáŹáşááźááŹá¸áááˇáşáĄááŹááťáŹá¸áážááˇáş áĄááąáŹáşááąá¸áááŻááşááŽááŤáááşá ááąááŹááᯠá
áááşááŻááşááąáŹááşáááŻááşááŤáááşá
ááŻááşáá˝á˛ááźááşá¸á
ááááŚá¸á á˝áŹáááş bitstream áááŻááá°áááşáááŻáĄááşáááşá áĄááťááşááźááᯠáááşááťááşá áᏠááŻááşááźááˇáş ááŻááşááŻááşááŹá¸áááş-

nibbles ááťáŹá¸áá˝ááş áĄáááˇáşááťáŹá¸áá˝áŹááźáŹá¸áážáŻááž áĄá
á
áşáĄáážááş "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 += "0"
elif avg1 > avg2:
bits_str += "1"
signal áááŻááşáááŻááşáá˝á˛áˇá ááşá¸ááŻáśáážáŹ áĄáąáŹááşááŤáĄáááŻááşá¸ááźá áşáááşá

áĄáá˝ááşáá˝áąááᯠáĄááąá¸á
áááşááźááˇáşááĄáąáŹááşá
DF (ááąáŤááşá¸ááŻááşáááˇáşááşááŻáśá áśá 5 bits) â áááşááąáˇááşáťáĄááťááŻá¸áĄá áŹá¸ááᯠáááşáážááşáááşá áĄááťááŻá¸áĄá áŹá¸ááťáŹá¸á á˝áŹáážááááş-

()
ááąááŹááşááźááááááşááťáŹá¸ááŤáááşááąáŹááźáąáŹááˇáş DF17 áĄááťááŻá¸áĄá áŹá¸ááᯠááťá˝ááşáŻááşáááŻáˇá áááşáááşá áŹá¸ááŤáááşá
ICAO (24 bits) â ááąááŹááşá áááŻááşááśááᏠáá°á¸ááźáŹá¸ááąáŹ ááŻááşá ááąááŹááşááᯠáááşá¸áááŻááşááźááˇáş á á áşááąá¸áááŻááşáááşá (ááśáááąáŹááşá¸á á˝áŹááźááˇáşá á áŹááąá¸áá°áááş ááąááŹááąáˇá áşááᯠáá˝ááşá¸ááśáá˝ááşá¸ááśááźááşá¸ááᯠáááşáááŻááşááąáŹáşáááşá¸ áááşá¸áááş áááşáááŻááşáá˛ááźá áşáááş)á áĽáááŹáĄáŹá¸ááźááˇáşá ááŻááş 3c5ee2 áĄáá˝ááş ááťá˝ááşáŻááşáááŻáˇáá˝ááş áĄáąáŹááşááŤáĄááťááşáĄáááşááťáŹá¸ áážááááşá

áááşá¸ááźááşáááş ICAO ááŻááşá áážááşá¸áááşá¸ááťááşáĄáŹá¸ áĄááąá¸á
áááşááąáŹáşááźááŹá¸ááąáŹááźáąáŹááˇáş á
áááşáááşá
áŹá¸áá°ááťáŹá¸ áááşááźááˇáşáááş áĄááźáśááźáŻáĄááşááŤáááşá
áĄááťááşáĄáááş (56 áááŻáˇáááŻááş 112 bits) â ááťá˝ááşáŻááşáááŻáˇ ááŻááşááŻááşáááˇáş ááááˇáşááąááŹá áááááŻáśá¸ááąáᏠ5 bits áááş áĄáá˝ááşááźá áşáááşá Code áááŻáááŻááşááŤááááşá¸áááşá¸ááŹá¸ááąáŹááąááŹá áĄááťááŻá¸áĄá áŹá¸áá˝á˛áá áşááŻááŤáážááááş (DF áážááˇáş áááąáŹáá˝áąá¸á)á áááŻáá˛áˇáááŻáˇááąáŹ áĄááťááŻá¸áĄá áŹá¸ááťáŹá¸ ááťáŹá¸á á˝áŹáážáááŤáááşá

()
áááşááąáˇááťáşáá˝áąáá˛áˇ áĽáááŹáĄááťááŻáˇááᯠááźááˇáşááźááĄáąáŹááşá
ááąááŹááşáážááşááŻáśáááşááźááşá¸á
áĽááᏠbinary ááŻáśá áś-
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("Aircraft Identification:", code_str.replace('#', ''))
ááąáááşáĄááąáĄááŹá¸
ááŹáááşá áááŻá¸áááŻá¸áááŻáááş ááźááááááşáá˝áąá áááŻáážáŻááşáá˝áąá¸áááşá áááşá¸áááŻáˇááᯠ2xá áĄááąáŹááşáážááˇáş odd frames ááťáŹá¸áĄááźá áş ááŻááşáá˝ážááˇáşáááşá áĄáá˝ááşááŻááş TC = 01011b = 11á

áĄááŽáážááˇáş odd packets ááťáŹá¸á áĽáááŹ-
01011 000 000101110110 00 10111000111001000 10000110101111001
01011 000 000110010000 01 10010011110000110 10000011110001000
ááźááŽááááşááťáŹá¸ááᯠáá˝ááşááťááşááźááşá¸áááş áĄááąáŹáşááąá¸ áááşá¸ááťááşááąáŹ ááąáŹáşááźá°ááŹáĄá ááźá áşááąáŤáşáááş-

()
ááťá˝ááşáŻááşáááş GIS ááťá˝ááşá¸ááťááşáá°áááŻááşááŤá áááŻáˇááźáąáŹááˇáşáááşá¸áááşáááşáááŹáááşáááááŤá áááá˛áˇáá°ááťáŹá¸áážááááş comment áážáŹááąá¸ááąá¸ááŤá
áĄááźááˇáşááᯠáááŻáááŻáááŻá¸áážááşá¸á á˝áŹ áá˝ááşááťááşáááş - ááááťááąáŹ bit ááąáŤáşáá°áááşá áááşá¸ááᯠ25 ááą áááŻáˇáááŻááş 100 ááąá áĄáááŻá¸ááááşá¸áĄááźá áş áááŻááşá áŹá¸ááźáŻáááŻááşáááşá
ááąáááşáĄááťááş
TC=19 ááŤááąáŹ ááŻááşáááŻá¸áážáŻá á¤ááąááŹáá˝ááş á áááşáááşá áŹá¸á ááŹááąáŹááşá¸áááşáážáŹ áĄááźááşáážáŻááşá¸áááş ááźáąááźááş (Ground Speed) áááŻáˇáááŻááş ááąááŹááşáĄáŹááŻáśááśáááááᏠ(Airspeed) ááźááˇáş áááŻááşá¸ááŹááąáŹ ááąáĄááźááşáážáŻááşá¸áážááˇáş áĄáááĄááť ááźá áşáááŻááşáááşá ááá°ááŽááąáŹáááşáááşááťáŹá¸á á˝áŹáááŻáááşá¸ áááŻáˇáá˝ážááşáááş-

()
ááąáŹááşááťááş
áááşáá˝áąáˇááźááşááááˇáşáĄáááŻááşá¸ ADS-B áááşá¸áááŹáááş áááşáááˇáşá áśáážáŻááşá¸áááᯠááťá˝ááşá¸ááťááşáá°ááťáŹá¸áĄáá˝ááşááŹáá ááŹáááşáĄááŻáśá¸ááźáŻáá°ááťáŹá¸áĄáá˝ááşá፠áĄááŻáśá¸áááşááŹááąáŹáĄááŤáá˝ááş ADS-B áááşá¸áááŹáááş á áááşáááşá áŹá¸á ááŹááąáŹááşá¸áááˇáş ááąáŤááşá¸á ááşáážáŻáá áşáᯠááźá áşááŹáá˛áˇáááşá áááŻáˇááąáŹáşá á¤áĄááŹáá˝ááş áĄááááĄáááşá¸ááášááážáŹ áá áşááťá áşáááş SDR áááşááśáá°áááşá¸áááŹááᯠá áťáąá¸ááąáŤááąáŤááźááˇáş ááŻááşááąáŹááşáá˛áˇááźááşá¸ááźá áşááźáŽá¸á á ááşáá ášá ááşá¸áááş ááŽááŤáááşááşá áŹááŹá¸áĄá "for pennies" áááş ááźáááşáážáŻááşá¸áááŻáááŻááźááˇáşááŹá¸ááąáŹ áĄááťááşááźáážáŻááťáŹá¸ááᯠáááşááśááážáá áąááźááşá¸ááźááˇáş ááŤáááşáá˛áˇáááşá
ááŻááşááŤáááşá á áśáááŻááşáááŻááşá áĄááťáŹá¸ááźáŽá¸áážáááŤááąá¸áááşá áááŻááťááşáá°ááťáŹá¸ Page áá˝ááş PDF ááᯠááźááˇáşáážáŻáááŻááşááŤáááşá áááŻáˇáááŻááş áĄáááşááąáŹáşááźááŤáĄáááŻááşá¸ áá˝áŹá¸ááąáŹááşááźááˇáşáážáŻááŤá .
áĄáááşáá˝ááşááąá¸ááŹá¸áááˇáşáĄááŹáĄáŹá¸ááŻáśá¸áááş áĄááŻáśá¸áááşáááşáᯠáá°áĄááťáŹá¸á áááşááźááşáá°ááááşáááŻááşááąáŹáşáááşá¸ áĄáááşá¸ááŻáśá¸ áááşá¸áááşáá˛áˇáááŻáˇáĄááŻááşááŻááşááŻáśá ááąáá°ááťáĄáá°áĄááážáŹ ááťááşáážáááąáŚá¸áááşáᯠááťážáąáŹáşáááˇáşááŤáááşá
á ááŹá¸áá ááşá Python áá˝ááş áĄáááşáááˇáşááŻááşááŹá¸ááąáŹ ááŽááŻááşááŤáá áşáᯠáážááážááˇáşááźáŽá¸ááźá áşá áááşá¸ááᯠáááşááąáˇááŹáááŻááşáááşá . SDR áááşááśááááááŹááťáŹá¸á áááŻááşáážááşááťáŹá¸áááş áĄáááşáááˇáşááŻááşááŹá¸ááąáŹ ADS-B ááŽááŻááşááŤááᯠá áŻá ááşá¸áᏠá áááşáááŻááşáááşá á á¤áĄááźáąáŹááşá¸áĄááąá¸á áááşáĄááťááşáĄáááşááťáŹá¸áááŻáááˇáşáá˝ááşá¸áá˛áˇáááşá .
ááąáŹááşá¸ááŤá¸áá˝ááşááąáŹáşááźááŹá¸ááąáŹ parser ááĄáááşá¸áĄááźá
áşááŻááşáááŻááźááşááąáŹááşáážáŻáĄáąáŹááşáá˝ááşááąá¸ááŹá¸áááşá á¤áááşáážáŹ á
ááşá¸áááşáážáŻááá°ááŹáá
áşááŻááźá
áşááźáŽá¸ ááŻááşááŻááşáááşáĄáá˝ááş áááşáá˝ááşááźááşá¸áááŻááşáᲠáĄááťááŻáˇáĄááŹááťáŹá¸áááş áááşá¸áá˝ááşáĄááŻááşááŻááşááźáŽá¸ áĄáááşáá˝ááşááąá¸ááŹá¸ááąáŹáááŻááşááᯠáááşá¸áážááˇáşáá˝á˛ááźááşá¸á
áááşááźáŹáááŻááşáááşá
áĄáááşá¸áĄááźá
áşááŻááş (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()
áá áşááąáŹááşááąáŹááşá á áááşáááşá áŹá¸áááŻáˇááąáŹááşá¸áááşáááŻáˇ ááťážáąáŹáşáááˇáşááŤáááşá áááşá¸áá˛áˇáĄáŹááŻáśá ááŻááşáážáŻáĄáá˝ááş ááťáąá¸áá°á¸áááşááŤáááşá
source: www.habr.com
