D2
Администратор
- Регистрация
- 19 Фев 2025
- Сообщения
- 4,380
- Реакции
- 0
Взгляни на небо! Возможно, над твоей головой каждые несколько минут будет пролетать самолет, а то и не один. Я живу недалеко от аэропорта, и воздушный трафик в моем районе особенно сильный. Сервисы вроде Flightradar24 удивительно точно показывают информацию о самолетах в воздухе, потому что получают данные по протоколу ADS-B. Это можно делать самостоятельно, и сегодня я покажу как.
Каждый, конечно, летал на самолете или видел его хоть раз в своей жизни. Большие металлические птицы кружат над всей планетой и доставляют сотни миллионов людей в разные части света. Так было не всегда: еще каких‑то 100 лет назад люди могли перемещаться только по земле, а сверхнадежных летательных аппаратов не было.
Уже после изобретения самолетов и начала коммерческих рейсов стало понятно, что надо как‑то отслеживать все находящиеся в воздухе судна, иначе аварий не избежать. Радары или тем более визуальное наблюдение для этого годятся плохо, и в ход пошла радиосвязь. Теперь на борту каждого самолета стоит авиационный транспондер. Он сильно облегчает работу диспетчерам и пилотам и позволяет в полете передавать данные с бортовых датчиков и получать указания с земли.
Простым языком авиационный транспондер — это устройство двунаправленной радиосвязи, которое делает две вещи:
Ты можешь купить себе собственный транспондер — их можно легко найти на eBay по цене до пяти тысяч долларов.
Многие выделяют ADS-B как отдельный режим работы транспондера, на уровне Mode A, C или S, но на самом деле это всего лишь часть одного большого режима S. Сообщение ADS-B — это просто сообщение Mode S, имеющее тип 17.
Все сообщения Mode S передаются на самолет на частоте 1030 МГц, а на землю — на частоте 1090 МГц.
Сама радиопередача никак не шифруется, а передается масса интересной информации о местонахождении самолета, его высоте, скорости и других параметрах, так что в какой‑то момент появились сервисы вроде Flightradar24, которые сделали информацию о самолетах доступной всем и даром. Сами сервисы эту информацию получают от большого количества датчиков, установленных у добровольцев по всему миру. Ты тоже можешь стать одним из них — достаточно просто изъявить желание и получить от владельцев сервиса датчик для установки.
Для кодирования используется PPM (Pulse-Position Modulation). Грубо говоря, в эфир просто передаются биты, которые можно прочитать, сделав выборку каждые N микросекунд. Это хорошо видно на изображении из Википедии.
В ADS-B длительность каждого такого бита равна 0,5 мкс, а значит, можно сделать выборку каждые 0,5 мкс, увидеть высокий или низкий уровень каждого бита, записать, а потом преобразовать результат в байты, чтобы получить исходное сообщение. Но это в теории, потому что на практике есть проблемы, с которыми мы будем разбираться по ходу повествования.
Пакет состоит из преамбулы и собственно данных. На картинке выше хорошо видно, что преамбула идет 8 мкс, а дальше в течение 56 или 112 мкс идут данные.
Вступление особенно важно, если вспомнить, что все самолеты вещают на одной частоте и сигналы от них могут приходить одновременно. Проблема потери накладывающихся сигналов решается очень просто: если что‑то не ловится, это поймает кто‑то другой. Приемников очень много, и покрывают они всю обитаемую площадь Земли, так что, если конкретный сигнал оказался слишком слабым и не был принят на одном приемнике, он будет достаточно громким для другого приемника и не потеряется. Конечно, такой подход не означает, что будут получены все сигналы, но это и не нужно — они регулярно повторяются, и от потери части сигналов беды не будет.
Я уже говорил, что каждый бит кодируется 0,5 мкс, и это действительно так, но для упрощения приема была введена условность: 1 настоящий бит кодируется двумя по 0,5 мкс. Единица при этом кодируется как 1 и 0, а ноль — как 0 и 1 (то есть данные 1011 будут выглядеть как 10011010). Это не усложняет приемник, но защищает от помех и позволяет надежно ловить сигнал. Без этой доработки передача нескольких нулей будет выглядеть как тишина в эфире, а так приемник всегда точно видит сигнал, даже если передаются нули.
Длина интересующего нас сообщения — 112 мкс, что как раз равно 112 бит (спасибо двухбитному кодированию!), и делится оно на пять основных блоков:
Всего у ADS-B 31 тип данных, но мы разберем только самые главные.
Код 1–4 — сообщение с идентификационными данными. Там содержится позывной и другие данные, связанные с регистрацией и опознавательными свойствами самолета (например, легкий летательный аппарат или тяжелый). Эти позывные показываются на терминалах в аэропортах и представляют собой номер рейса. Декодированное сообщение выглядит примерно так:
Код: Скопировать в буфер обмена
Код 5–8 — позиция на земле. Эти данные обычно используются, чтобы знать, где и на какой полосе находится самолет. В сообщении можно найти широту, долготу, скорость и направление движения самолета. Пример декодированного сообщения:
Код: Скопировать в буфер обмена
Код 9–19 — позиция в воздухе (обычно передается вместе с высотой). Важно понимать, что найти в примере ниже привычную широту и долготу нельзя, поскольку используется короткая нотация координат вместо нормальной. Что делать с такими координатами — расскажу ниже.
Код: Скопировать в буфер обмена
Код 19 — скорость воздушного судна.
Код: Скопировать в буфер обмена
Разбирать по битам структуру каждого сообщения можно очень долго, так что, если тебе действительно интересно, можно поискать готовые парсеры ADS-B на GitHub и подсмотреть структуру там. Нам же сейчас разбирать строение этих сообщений нет смысла еще и потому, что передавать мы пока что ничего не будем, а углубляться в тонкости протокола не хочется.
Тем не менее для записи координат используется формат CPR (Compact Position Reporting), который, как ясно из названия, предназначен для компактной передачи координат. Часть данных мы уже видели в примере сигнала с координатами выше. Поскольку ужать большое количество данных в маленький объем невозможно, эти данные просто разделили на части и отправляют в два захода, а пакеты стали называться просто «четный» и «нечетный». Как из этого получить нормальные координаты? Сейчас покажу!
Представим, что все самолеты летают в 2D-пространстве. Это одно пространство разделим на две сетки с разными параметрами и назовем их четной сеткой и нечетной. Четную сделаем 4 на 4, а нечетную — 5 на 5.
Допустим, мы хотим передать местоположение самолета в сетке размером 16 на 16 — пусть это будут координаты (9,7). Если бы у нас была одна сетка, то мы бы передали просто 9 и 7, а операторы бы у себя на карте нас нашли, но в CPR на самом деле сеток две.
В таких сетках мы укажем наше положение (9,7) в виде (1,3) на четной сетке (слева) и (4,2) в нечетной сетке (справа). Когда оператор получает оба сообщения, ему нужно совместить их на обеих сетках.
Если наложить сетки с полученным координатами друг на друга, в точке совпадения и будет находиться искомый объект.
Я описал алгоритм без математических выкладок и прочих сложностей, чтобы ты мог примерно представить себе, как работает восстановление координат из двух частей. Реальная сетка далека от случая из примера и выглядит, как на картинке ниже.
Лямбда — это и есть длина волны, а получить ее из частоты можно по формуле λ = C/f, где С — скорость света, а f — частота сигнала. Для 1090 МГц она будет примерно равна 27,5 см. Если взять металлический штырь такой длины, то у тебя получится так называемая полноволновая антенна, которую можно спокойно укоротить вдвое или даже в четыре раза, чтобы получить полуволновую или четвертьволновую антенну соответственно. Разница в чувствительности этих антенн, конечно, будет, так что советую использовать полуволновую антенну, длина которой составит примерно 13,75 см.
Если хочешь поколхозить по полной, почитай гайд, как сделать дипольную антенну для работы с ADS-B из пробки и проволоки.
Делать свою антенну я не буду — это не самое простое занятие, да и нужная антенна у меня уже была. Тебе могут подойти, например, антенны для раций, если принимать на открытом пространстве и вокруг не слишком много шумов. Я использую обычную штыревую coil-loaded-антенну, которая, по сути, работает как штыревая, но за счет катушки имеет меньшую длину.
Основные характеристики антенны можно измерить специальным векторным анализатором, который генерирует разные частоты и проверяет реакцию антенны на них.
Вывод анализатора кажется сложным на первый взгляд, но на самом деле все довольно просто. Чтобы узнать, годится ли антенна для какой‑то конкретной частоты, достаточно посмотреть на желтую линию SWR, которая по‑русски называется КСВ (коэффициент стоячей волны). Этот коэффициент показывает, какую часть сигнала антенна передала в эфир, а какая вернулась. Чем меньше сигнала вернулось, тем лучше антенна работает на конкретной частоте.
На приборе видно, что на метке 1 (я выставил ее на частоту 1090 МГц) SWR равен 1,73, что очень даже неплохо. Обычно хорошей антенной считается та, у которой КСВ около 1 (не больше 2).
Я буду использовать BladeRF micro — он поддерживает большой диапазон частот и имеет большую частоту выборки, о которой поговорим позже.
Если у тебя еще нет SDR — не беда, RTL-SDR стоит всего около 30 долларов и продается во многих интернет‑магазинах. Вот только имей в виду, что этот прибор умеет только принимать сигналы, но не умеет передавать их.
Для изучения эфира я буду использовать GQRX, эта программа доступна для Linux и macOS. Если у тебя Windows, рекомендую SDR#. В Ubuntu GQRX устанавливается из штатных репозиториев:
Код: Скопировать в буфер обмена
Дальше делаем звук погромче, выбираем источником наш SDR и нажимаем на большую кнопку «Старт». Если все сделано правильно, из динамиков начнет шипеть так, что ты подпрыгнешь на стуле, после чего отключишь звуки кнопкой Mute, расположенной в правом нижнем углу.
Частоту приема можно выбрать в верхней части экрана — нужно задать там значение 1.090.000, что равно 1090 МГц. После этого ты увидишь что‑то похожее на скриншот внизу.
Короткие полоски по центру — это и есть сигнал ADS-B, который заметно выделяется на фоне окружающего шума. Если у тебя их нет, попробуй изменить параметры усиления на вкладке Input Controls справа. Если и это не помогло, перейди на вкладку FFT Settings и настрой параметры Plot и WF. Еще можно попробовать покрутить антенну или положить ее в разных направлениях.
В обычных случаях, если кто‑то хочет просто принять сигналы Mode S и декодировать их, он использует уже готовую программу dump1090. Эта тулза с исходным кодом умеет демодулировать и декодировать почти все сигналы Mode S и даже выводит их в виде красивой таблички. Чтобы проверить, все ли у нас работает корректно, лучше начать с чего‑то заведомо рабочего, и начнем мы с dump1090.
Для установки нужно клонировать репозиторий проекта с GitHub и собрать бинарник. Делается это проще простого:
Код: Скопировать в буфер обмена
После этого у тебя должен появиться бинарник dump1090. Если у тебя RTL-SDR, можешь использовать dump1090 напрямую с ним, но у меня BladeRF, для поддержки которого нужно немного повозиться.
Во‑первых, установи драйвер для своего SDR — их можно найти в репозиториях практически всех дистрибутивов, погуглить.
Во‑вторых, нужно будет накатить на SDR специальную прошивку. Для BladeRF эти прошивки доступны на сайте Nuand, где нужно выбрать соответствующий файл для своей версии BladeRF.
Дальше скачиваем программу для декодирования сообщений ADS-B и собираем ее:
Код: Скопировать в буфер обмена
Теперь заливаем прошивку в BladeRF. Сделать это можно с помощью пакета bladerf-cli:
Код: Скопировать в буфер обмена
Теперь запускаем в одном окне dump1090, а в другом — bladeRF-adsb, который мы собирали парой шагов раньше:
Код: Скопировать в буфер обмена
Если все сделано верно, в окне с dump1090 ты увидишь кучу строк в шестнадцатеричном виде. Это и есть сообщения Mode S, которые надо еще декодировать и отфильтровать.
Если убрать
В таблице можно найти уже декодированные из CPR широту и долготу, позывной самолета, его скорость, высоту и другие данные. Но это было бы слишком просто, не правда ли? Давай декодировать эти данные самостоятельно!
Демодуляция (детектирование сигнала) — процесс, обратный модуляции колебаний, выделение информационного (модулирующего) сигнала из модулированного колебания высокой (несущей) частоты. Простым языком демодуляция — это выделение сигнала из колебаний высокой частоты.
ADS-B работает с PPM-модуляцией, то есть, чтобы выделить полезный сигнал, нужно каждые 0,5 мкс определять состояние сигнала (0 или 1). План у нас будет следующий:
Код: Скопировать в буфер обмена
Разумеется, для работы GNU Radio потребуются и драйверы для твоей SDR. При этом мы не будем использовать SDR как основной источник сигнала, чтобы можно было на заведомо одинаковых данных погонять разные алгоритмы и сравнить результаты.
Всего тут пять блоков, два из которых — опции и переменная. В самом начале стоит osmocom Source, который отвечает за получение сырых данных из SDR. Настроек в нем много, но для работы нужны всего пять (пример ниже — для BladeRF):
Количество столбиков на картинке — это и есть количество семплов, а SPS в скобках в названии этого параметра расшифровывается как Samples per Second, то есть количество выборок в секунду. В параметре samp_rate вверху я задал частоту выборки 4М SPS, и это неслучайное значение, ведь оно как раз в четыре раза больше частоты входного сигнала, а по теореме Найквиста нужна минимум в два раза большая частота, чем частота сигнала. Для работы с ADS-B можно использовать и частоты 2 и 2,5 MSPS, но чем выше частота дискретизации, тем лучше качество оцифровки.
Теорема Найквиста (она же теорема отсчетов, теорема Котельникова) — фундаментальное утверждение в области цифровой обработки сигналов, связывающее непрерывные и дискретные сигналы и гласящее, что «любую функцию F(t), состоящую из частот от 0 до f1, можно непрерывно передавать с любой точностью при помощи чисел, следующих друг за другом менее чем через 1 / (2 * f1) с».
Теперь, когда все настроено, можно нажимать «Старт» на верхней панели GNU Radio. Если все сделано верно, ты увидишь спектр, похожий на тот, что поймал я.
Еле заметные полоски в верхней части скриншота — это и есть сигналы, которые мы ищем. Мой BladeRF не откалиброван, так что по бокам видны завалы, но нашему эксперименту они не мешают. Нужно записать несколько минут таких сигналов, после чего можно сворачивать оборудование и идти домой — декодировать!
Давай пробежимся по каждому блоку схемы, чтобы ты понимал, что происходит. На схеме часть входов и выходов имеют разные цвета — эти цвета означают разные типы данных:
Самое первое — это наш Waterfall, на нем удобно глазами искать сигнал. Дальше идет Time Sink после синхронизации: тут два сигнала — красный (сигнал ошибки) и синий (исправленный по времени сигнал). Эти сигналы уже напоминают что‑то цифровое, но настоящий цифровой сигнал отображается уже на третьем графике (обработанный блоком Threshold). Четвертый график — это тот же исходный сигнал, что на первом графике, но обработанный блоком Threshold.
Код: Скопировать в буфер обмена
Давай теперь прочитаем файл и будем искать в этом потоке данных преамбулу пакета Mode S. Я написал для этого несколько функций на Python.
Python: Скопировать в буфер обмена
Первая функция просто читает файл, а вторая ищет заданный паттерн (нашу преамбулу). Но для поиска нужно сначала собрать двойные биты в одинарные (те самые повторения, из‑за которых бит по 0,5 мкс занимает 1 мкс). Следующая функция как раз это и делает:
Python: Скопировать в буфер обмена
Читаем файл и находим все преамбулы:
Код: Скопировать в буфер обмена
Здесь pattern — это и есть искомая преамбула. Можешь даже отлистать в начало статьи и сравнить. Поскольку преамбула означает любой сигнал Mode S, а не только ADS-B, то могут попадаться сигналы длиной 56 бит. Их поддержка тоже есть.
Python: Скопировать в буфер обмена
Прочитав код, ты заметишь, что я вытаскиваю ADS-B-пакеты и отправляю их для декодирования на сторонний сервис, чтобы не изобретать собственный парсер для всех типов пакетов. Этот же сайт можно открыть и просто в браузере, чтобы полистать образцы пакетов и еще глубже окунуться в мир Mode S и ADS-B.
При хорошем раскладе ты увидишь примерно такой вывод:
Код: Скопировать в буфер обмена
Я получил сигнал со скоростью самолета, но у тебя, конечно, будет их намного больше. DF у меня равен 17 (ADS-B), а ICAO-код транспондера — 896179.
Надеюсь, и тебе понравилось погружение в интересный мир радиосигналов. Приятных исследований!
Источник xakep.ru
Автор @qeewqq
t.me/qeewqw

Каждый, конечно, летал на самолете или видел его хоть раз в своей жизни. Большие металлические птицы кружат над всей планетой и доставляют сотни миллионов людей в разные части света. Так было не всегда: еще каких‑то 100 лет назад люди могли перемещаться только по земле, а сверхнадежных летательных аппаратов не было.
Уже после изобретения самолетов и начала коммерческих рейсов стало понятно, что надо как‑то отслеживать все находящиеся в воздухе судна, иначе аварий не избежать. Радары или тем более визуальное наблюдение для этого годятся плохо, и в ход пошла радиосвязь. Теперь на борту каждого самолета стоит авиационный транспондер. Он сильно облегчает работу диспетчерам и пилотам и позволяет в полете передавать данные с бортовых датчиков и получать указания с земли.
Простым языком авиационный транспондер — это устройство двунаправленной радиосвязи, которое делает две вещи:
- Отвечает на запросы наземных станций: когда диспетчер запрашивает данные, а транспондер отвечает ему в автоматическом режиме. Запрос данных еще называется интеррогацией (это слово в переводе с английского означает «допрос свидетеля»).
- Служит радиомаяком воздушного судна: в этом режиме транспондер раз в некоторое время передает информацию о себе, например местоположение или скорость.
- Mode A передает только идентификационный номер летательного аппарата. Этот номер может быть жестко зашит в транспондер или назначен диспетчером перед вылетом. На практике использовался только для отслеживания того, в каком аэропорту находится самолет.
- Mode C, созданный позже, позволял отслеживать не только номер аппарата, но и высоту его полета. Главное его преимущество было в том, что он позволял получать высоту самолета автоматически, не спрашивая ее у пилота.
- Mode S — это современный режим, который сейчас используется на 99% всех самолетов. Позволяет не только получать данные с бортовых датчиков, но и отправить данные обратно на самолет. В этом режиме самолет имеет полную двустороннюю связь с наземными станциями. ADS-B, который мы будем рассматривать сегодня, является частью этого режима.
- Mode 4 и Mode 5 более продвинутые, но используются только военными. Оба они защищены куда лучше (то есть вообще хоть как‑то защищены, в отличие от прошлых), и поковыряться там не получится.
Ты можешь купить себе собственный транспондер — их можно легко найти на eBay по цене до пяти тысяч долларов.
ADS-B
Если внимательно почитать описание Mode S, можно заметить, что сообщения, которые передаются по этому протоколу, должны отправляться транспондером по запросу наземного диспетчера — все, кроме ADS-B (Automatic Dependent Surveillance — Broadcast). На русский язык это вольно переводится как «автоматическая система слежения за самолетами». Слово Broadcast тут означает, что сообщения передаются всем подряд, а не кому‑то конкретному, и это открывает перед нами возможность их принимать.Многие выделяют ADS-B как отдельный режим работы транспондера, на уровне Mode A, C или S, но на самом деле это всего лишь часть одного большого режима S. Сообщение ADS-B — это просто сообщение Mode S, имеющее тип 17.
Типы сообщений Mode S
В этой статье рассматривается только ADS-B (тип 17), но для общего развития будет нелишним знать и про другие типы сообщений Mode S:- All-call reply (тип 11) — в этом сообщении по запросу оператора передается уникальный 24-битный идентификатор транспондера. Этот номер обычно прошивается на заводе и не меняется, но в военных целях этот номер иногда подменяют.
- ACAS short and long replies (тип 0/16) — сообщения для предотвращения столкновений между самолетами. Если транспондер обнаружит поблизости другой самолет, он отправит оповещение другим системам, которые смогут предотвратить столкновение в воздухе.
- Altitude and identity replies (тип 4/5) — сообщение с данными о высоте и позывном (так называемый squawk-код, который пилот вводит вручную перед полетом).
- Comm-B (тип 20/21) — это сообщения с показаниями бортовых датчиков, намеченным маршрутом и другими данными, которые могут быть полезны для управления судном.
Все сообщения Mode S передаются на самолет на частоте 1030 МГц, а на землю — на частоте 1090 МГц.
Сама радиопередача никак не шифруется, а передается масса интересной информации о местонахождении самолета, его высоте, скорости и других параметрах, так что в какой‑то момент появились сервисы вроде Flightradar24, которые сделали информацию о самолетах доступной всем и даром. Сами сервисы эту информацию получают от большого количества датчиков, установленных у добровольцев по всему миру. Ты тоже можешь стать одним из них — достаточно просто изъявить желание и получить от владельцев сервиса датчик для установки.
Физическая структура сигнала
Сигналы ADS-B самолет передает на частоте 1090 МГц, как и все остальные сигналы Mode S. Вторая частота — 1030 МГц (uplink) — тут не нужна, потому что сигналы ADS-B передаются без запроса.Для кодирования используется PPM (Pulse-Position Modulation). Грубо говоря, в эфир просто передаются биты, которые можно прочитать, сделав выборку каждые N микросекунд. Это хорошо видно на изображении из Википедии.

В ADS-B длительность каждого такого бита равна 0,5 мкс, а значит, можно сделать выборку каждые 0,5 мкс, увидеть высокий или низкий уровень каждого бита, записать, а потом преобразовать результат в байты, чтобы получить исходное сообщение. Но это в теории, потому что на практике есть проблемы, с которыми мы будем разбираться по ходу повествования.
Структура пакета
Если принять данные как есть, получится битовая каша, из которой еще нужно вытащить полезные данные. Сами они имеют очень четкую структуру, так что, если заметить ее постоянные части в потоке данных, можно будет получить и весь пакет.
Пакет состоит из преамбулы и собственно данных. На картинке выше хорошо видно, что преамбула идет 8 мкс, а дальше в течение 56 или 112 мкс идут данные.
Вступление особенно важно, если вспомнить, что все самолеты вещают на одной частоте и сигналы от них могут приходить одновременно. Проблема потери накладывающихся сигналов решается очень просто: если что‑то не ловится, это поймает кто‑то другой. Приемников очень много, и покрывают они всю обитаемую площадь Земли, так что, если конкретный сигнал оказался слишком слабым и не был принят на одном приемнике, он будет достаточно громким для другого приемника и не потеряется. Конечно, такой подход не означает, что будут получены все сигналы, но это и не нужно — они регулярно повторяются, и от потери части сигналов беды не будет.
Я уже говорил, что каждый бит кодируется 0,5 мкс, и это действительно так, но для упрощения приема была введена условность: 1 настоящий бит кодируется двумя по 0,5 мкс. Единица при этом кодируется как 1 и 0, а ноль — как 0 и 1 (то есть данные 1011 будут выглядеть как 10011010). Это не усложняет приемник, но защищает от помех и позволяет надежно ловить сигнал. Без этой доработки передача нескольких нулей будет выглядеть как тишина в эфире, а так приемник всегда точно видит сигнал, даже если передаются нули.
Структура полезных данных
Предположим, мы декодировали сигнал и нашли в нем сообщение. Теперь нужно декодировать блок полезных данных и отсеять ненужное (то есть все сообщения Mode S, кроме ADS-B).
Длина интересующего нас сообщения — 112 мкс, что как раз равно 112 бит (спасибо двухбитному кодированию!), и делится оно на пять основных блоков:
- DF (Downlink Format) — код формата передачи, 5 бит. Для ADS-B он всегда равен 17.
- CA (Transponder capability) — тип передатчика и его уровень возможностей, 3 бита. Нужно это поле для того, чтобы диспетчер знал, какие данные можно запрашивать у этого транспондера. Это поле может иметь значение 0, 4, 5 или 6, а 1–3 и 7 зарезервированы для будущего использования. 0 — это транспондер первого уровня, и обычно такие транспондеры не имеют ACAS (системы предотвращения столкновений). 4 — это транспондер второго или более совершенного уровня, тоже не имеющий ACAS, но умеющий передавать высоту (то есть работать с Mode C и Mode S). 5 и 6 — это тот же 4, но с поддержкой ACAS, который может быть включен (6) или выключен (5).
- ICAO — уникальный номер самолета, 24 бита. Номер нужен для определения отправителя сигнала. Этот номер однократно прошивается на заводе и никогда не меняется в процессе эксплуатации, но все же есть ребята, которые умеют их менять. Существуют еще военные транспондеры, но на них вообще никакие правила не действуют, так что там может быть что угодно.
- ME (Message) — собственно полезная нагрузка с данными о высоте, скорости или чем‑то другим, длина — 56 бит. Этот блок мы будем подробно разбирать ниже.
- PI (Parity/Interrogator ID) — контрольная сумма, 24 бита.
Поле ME
Поле ME — это самая интересная для нас часть, ведь именно тут передаются координаты, скорость полета, высота и другие данные с бортовых датчиков. 56 бит маловато для передачи всех данных разом, так что у каждого сообщения свой тип, который указывается в первых пяти битах этого поля. Получается эдакая матрешка: свой формат сообщения у Mode S, чтобы обозначить ADS-B, и свой формат сообщения внутри ADS-B, чтобы сказать, что за данные внутри.Всего у ADS-B 31 тип данных, но мы разберем только самые главные.
Код 1–4 — сообщение с идентификационными данными. Там содержится позывной и другие данные, связанные с регистрацией и опознавательными свойствами самолета (например, легкий летательный аппарат или тяжелый). Эти позывные показываются на терминалах в аэропортах и представляют собой номер рейса. Декодированное сообщение выглядит примерно так:
Код: Скопировать в буфер обмена
Код:
ME : ADSB Msg Type : (4) Aircraft Identification and Category
CAT: Aircraft Cat : (0:0) No ADS-B Emitter Category Information
flight Number : SIA224
Wake Type : (TC:4 CAT:0) - No Information Provided
Код: Скопировать в буфер обмена
Код:
ME : ADSB Msg Type : (7) Surface Position
Super Sonic? : No
velocity : 0.00
EW/NS VEL : (East/west: 0) (North/South: 0)
heading : 253.12
Before Decoding : Half of vehicle location
UTC Sync? : false
CPR Frame : Odd
CPR latitude : 8675
CPR longitude : 17674
Код: Скопировать в буфер обмена
Код:
ME : ADSB Msg Type : (14) Airborne Position (with Barometric altitude)
Containment Radius: 1852.00 metres
Surveillance : (status:0) No condition information
NIC Supplement B : 0
Nav Integrity : 5
AC: altitude : 3100 feet (q bit: false, m bit: false)
Before Decoding : Half of vehicle location
UTC Sync? : true
CPR Frame : Odd
CPR latitude : 101906
CPR longitude : 103292
Код: Скопировать в буфер обмена
Код:
ME : ADSB Msg Type : (19) Airborne velocity
SUB: Sub Type : 3
Intent Change : false
IFR Capable : true
Nav Accuracy Cat : 0
heading : 8.44
Super Sonic? : No
velocity : 136.00
EW/NS VEL : (East/west: 0) (North/South: 0)
Vertical Rate : -768
HAE Delta : Unavailable
CPR, ИЛИ КАК УСЛОЖНИТЬ ПРОСТОЕ
Для точного определения координат обычно используются два числа — широта и долгота. 32 бита float обеспечивают точность до семи знаков после запятой, что в пересчете на координаты дает точность порядка нескольких сантиметров, а если чуть уменьшить точность (до десятков сантиметров), то два таких числа как раз можно запихнуть в 56 бит сообщения, и не придется городить неведомо что с компактными координатами. Точность даже в десятки сантиметров для самолета, летящего со скоростью больше 100 м/с, просто огромна, так что, чем руководствовались авторы протокола, понять сложно.Тем не менее для записи координат используется формат CPR (Compact Position Reporting), который, как ясно из названия, предназначен для компактной передачи координат. Часть данных мы уже видели в примере сигнала с координатами выше. Поскольку ужать большое количество данных в маленький объем невозможно, эти данные просто разделили на части и отправляют в два захода, а пакеты стали называться просто «четный» и «нечетный». Как из этого получить нормальные координаты? Сейчас покажу!
Представим, что все самолеты летают в 2D-пространстве. Это одно пространство разделим на две сетки с разными параметрами и назовем их четной сеткой и нечетной. Четную сделаем 4 на 4, а нечетную — 5 на 5.
Допустим, мы хотим передать местоположение самолета в сетке размером 16 на 16 — пусть это будут координаты (9,7). Если бы у нас была одна сетка, то мы бы передали просто 9 и 7, а операторы бы у себя на карте нас нашли, но в CPR на самом деле сеток две.

В таких сетках мы укажем наше положение (9,7) в виде (1,3) на четной сетке (слева) и (4,2) в нечетной сетке (справа). Когда оператор получает оба сообщения, ему нужно совместить их на обеих сетках.

Если наложить сетки с полученным координатами друг на друга, в точке совпадения и будет находиться искомый объект.

Я описал алгоритм без математических выкладок и прочих сложностей, чтобы ты мог примерно представить себе, как работает восстановление координат из двух частей. Реальная сетка далека от случая из примера и выглядит, как на картинке ниже.

ПРОСТОЙ СПОСОБ ПРИНЯТЬ ADS-B
Теперь, когда мы знаем устройство всех основных частей протокола, можно попробовать принять реальный сигнал. Для приема любого подобного сигнала потребуются три базовые вещи: антенна, приемник и ПК.Антенна
Начнем с самого важного предмета, без которого не обходится никакая радиосвязь, — антенны. Выбор антенны зависит от множества факторов, включая частоту, направленность сигнала, среду его прохождения. Наш сигнал передается на частоте 1090 МГц, и принимать мы его будем на открытом воздухе. Самый простой вариант (но не самый эффективный) — это обычная штыревая антенна. Такую антенну можно сделать из куска провода или проволоки, главное здесь — правильно рассчитать ее длину. Длина антенны зависит от длины волны, которую мы хотим на эту антенну принимать. Длина волны — это расстояние между двумя соседними «горбами» сигнала (на рисунке снизу).
Лямбда — это и есть длина волны, а получить ее из частоты можно по формуле λ = C/f, где С — скорость света, а f — частота сигнала. Для 1090 МГц она будет примерно равна 27,5 см. Если взять металлический штырь такой длины, то у тебя получится так называемая полноволновая антенна, которую можно спокойно укоротить вдвое или даже в четыре раза, чтобы получить полуволновую или четвертьволновую антенну соответственно. Разница в чувствительности этих антенн, конечно, будет, так что советую использовать полуволновую антенну, длина которой составит примерно 13,75 см.
Если хочешь поколхозить по полной, почитай гайд, как сделать дипольную антенну для работы с ADS-B из пробки и проволоки.
Делать свою антенну я не буду — это не самое простое занятие, да и нужная антенна у меня уже была. Тебе могут подойти, например, антенны для раций, если принимать на открытом пространстве и вокруг не слишком много шумов. Я использую обычную штыревую coil-loaded-антенну, которая, по сути, работает как штыревая, но за счет катушки имеет меньшую длину.

Основные характеристики антенны можно измерить специальным векторным анализатором, который генерирует разные частоты и проверяет реакцию антенны на них.

Вывод анализатора кажется сложным на первый взгляд, но на самом деле все довольно просто. Чтобы узнать, годится ли антенна для какой‑то конкретной частоты, достаточно посмотреть на желтую линию SWR, которая по‑русски называется КСВ (коэффициент стоячей волны). Этот коэффициент показывает, какую часть сигнала антенна передала в эфир, а какая вернулась. Чем меньше сигнала вернулось, тем лучше антенна работает на конкретной частоте.
На приборе видно, что на метке 1 (я выставил ее на частоту 1090 МГц) SWR равен 1,73, что очень даже неплохо. Обычно хорошей антенной считается та, у которой КСВ около 1 (не больше 2).
Приемник
В качестве приемника мы будем использовать SDR-донгл. Он представляет собой обыкновенное радио, которое управляется с помощью специальных программ, а не крутилкой с делениями, как на дедовских приемниках. Для приема ADS-B подойдет любой SDR-адаптер, начиная с самого дешевого RTL-SDR и заканчивая дорогими BladeRF и ему подобными. Цена дешевых вариантов начинается от 30 долларов, так что приобщиться может каждый.Я буду использовать BladeRF micro — он поддерживает большой диапазон частот и имеет большую частоту выборки, о которой поговорим позже.

Если у тебя еще нет SDR — не беда, RTL-SDR стоит всего около 30 долларов и продается во многих интернет‑магазинах. Вот только имей в виду, что этот прибор умеет только принимать сигналы, но не умеет передавать их.
Собираем всё вместе
Теперь, когда у тебя есть антенна и SDR, нужно найти свободное от помех и препятствий место — я просто выехал за город километров на десять. Сигналы около 1 ГГц (к которым относится и наш ADS-B) почти не распространяются за горизонт, так что, если ты не живешь около аэропорта и вокруг есть препятствия, можно не поймать вообще ничего.Как улучшить прием
Между антенной и SDR можно добавить фильтр, который отсечет часть шумов. Существуют специальные фильтры для ADS-B, заказать из Китая можно за 10–15 долларов.Для изучения эфира я буду использовать GQRX, эта программа доступна для Linux и macOS. Если у тебя Windows, рекомендую SDR#. В Ubuntu GQRX устанавливается из штатных репозиториев:
Код: Скопировать в буфер обмена
Код:
apt update
apt install -y gqrx
Частоту приема можно выбрать в верхней части экрана — нужно задать там значение 1.090.000, что равно 1090 МГц. После этого ты увидишь что‑то похожее на скриншот внизу.

Короткие полоски по центру — это и есть сигнал ADS-B, который заметно выделяется на фоне окружающего шума. Если у тебя их нет, попробуй изменить параметры усиления на вкладке Input Controls справа. Если и это не помогло, перейди на вкладку FFT Settings и настрой параметры Plot и WF. Еще можно попробовать покрутить антенну или положить ее в разных направлениях.
Dump1090
Когда ты добьешься стабильного приема сигнала в GQRX, можешь переходить к следующему шагу.В обычных случаях, если кто‑то хочет просто принять сигналы Mode S и декодировать их, он использует уже готовую программу dump1090. Эта тулза с исходным кодом умеет демодулировать и декодировать почти все сигналы Mode S и даже выводит их в виде красивой таблички. Чтобы проверить, все ли у нас работает корректно, лучше начать с чего‑то заведомо рабочего, и начнем мы с dump1090.
Для установки нужно клонировать репозиторий проекта с GitHub и собрать бинарник. Делается это проще простого:
Код: Скопировать в буфер обмена
Код:
git clone https://github.com/antirez/dump1090
cd dump1090
make
Во‑первых, установи драйвер для своего SDR — их можно найти в репозиториях практически всех дистрибутивов, погуглить.
Во‑вторых, нужно будет накатить на SDR специальную прошивку. Для BladeRF эти прошивки доступны на сайте Nuand, где нужно выбрать соответствующий файл для своей версии BladeRF.
Дальше скачиваем программу для декодирования сообщений ADS-B и собираем ее:
Код: Скопировать в буфер обмена
Код:
git clone https://github.com/Nuand/bladeRF-adsb
cd bladeRF-adsb/bladeRF_adsb
make
Код: Скопировать в буфер обмена
bladeRF-cli -l ~/Downloads/adsbxA4.rbf
Теперь запускаем в одном окне dump1090, а в другом — bladeRF-adsb, который мы собирали парой шагов раньше:
Код: Скопировать в буфер обмена
Код:
~/Soft/dump1090/dump1090 --raw --device-type bladerf --bladerf-fpga ''
~/Soft/Blade/bladeRF-adsb

Если убрать
--raw
из аргументов запуска dump1090, то сигналы будут автоматически декодироваться и выводиться в таблицу, как на скриншоте ниже.
В таблице можно найти уже декодированные из CPR широту и долготу, позывной самолета, его скорость, высоту и другие данные. Но это было бы слишком просто, не правда ли? Давай декодировать эти данные самостоятельно!
СЛОЖНЫЙ СПОСОБ ПРИНЯТЬ ADS-B
Чтобы принять сигнал самостоятельно, нужно сначала демодулировать его, а потом декодировать то, что получится.Демодуляция (детектирование сигнала) — процесс, обратный модуляции колебаний, выделение информационного (модулирующего) сигнала из модулированного колебания высокой (несущей) частоты. Простым языком демодуляция — это выделение сигнала из колебаний высокой частоты.
ADS-B работает с PPM-модуляцией, то есть, чтобы выделить полезный сигнал, нужно каждые 0,5 мкс определять состояние сигнала (0 или 1). План у нас будет следующий:
- Записать сигнал.
- Сделать выборки каждые 0,5 мкс.
- Преобразовать их в байты.
- Декодировать сообщения ADS-B.
Код: Скопировать в буфер обмена
Код:
sudo add-apt-repository ppa:gnuradio/gnuradio-releases -y
sudo apt update
sudo apt install gnuradio -y
Запись сигнала
Первое, что нужно сделать после запуска GNU Radio, — это собрать базовый пайплайн. Выглядеть он будет, как на скриншоте ниже.
Всего тут пять блоков, два из которых — опции и переменная. В самом начале стоит osmocom Source, который отвечает за получение сырых данных из SDR. Настроек в нем много, но для работы нужны всего пять (пример ниже — для BladeRF):
- Device Argument — аргументы, которые будут переданы SDR. Тут вписываем bladerf=0.
- Ch0 Freq — частота нулевого канала. У BaldeRF их два, но нам нужен только один. Сюда вписываем частоту ADS-B — это 1090 МГц или 1,09 ГГц.
- RF Gain — параметр, задающий чувствительность приемника. Я установил его в 15 дБ. Не ставь слишком большую чувствительность — мощные сигналы могут повредить радиотракт!
- Bandwidth — ширина канала приема, для ADS-B это 2 МГц.

Количество столбиков на картинке — это и есть количество семплов, а SPS в скобках в названии этого параметра расшифровывается как Samples per Second, то есть количество выборок в секунду. В параметре samp_rate вверху я задал частоту выборки 4М SPS, и это неслучайное значение, ведь оно как раз в четыре раза больше частоты входного сигнала, а по теореме Найквиста нужна минимум в два раза большая частота, чем частота сигнала. Для работы с ADS-B можно использовать и частоты 2 и 2,5 MSPS, но чем выше частота дискретизации, тем лучше качество оцифровки.
Теорема Найквиста (она же теорема отсчетов, теорема Котельникова) — фундаментальное утверждение в области цифровой обработки сигналов, связывающее непрерывные и дискретные сигналы и гласящее, что «любую функцию F(t), состоящую из частот от 0 до f1, можно непрерывно передавать с любой точностью при помощи чисел, следующих друг за другом менее чем через 1 / (2 * f1) с».
Теперь, когда все настроено, можно нажимать «Старт» на верхней панели GNU Radio. Если все сделано верно, ты увидишь спектр, похожий на тот, что поймал я.

Еле заметные полоски в верхней части скриншота — это и есть сигналы, которые мы ищем. Мой BladeRF не откалиброван, так что по бокам видны завалы, но нашему эксперименту они не мешают. Нужно записать несколько минут таких сигналов, после чего можно сворачивать оборудование и идти домой — декодировать!
Демодуляция
Для демодуляции я собрал в GNU Radio более сложную и интересную схему.
Давай пробежимся по каждому блоку схемы, чтобы ты понимал, что происходит. На схеме часть входов и выходов имеют разные цвета — эти цвета означают разные типы данных:
- синий — комплексные числа;
- оранжевый — числа с плавающей точкой;
- фиолетовые — байты.
- File Source — источник сигнала в виде файла. В этом блоке нужно выбрать файл, который мы записали, когда принимали сигнал. Этот блок заменяет реальную SDR для наших экспериментов.
- Throttle — элемент, замедляющий подачу сигнала в нашу схему. Без этого блока вся обработка выполнится слишком быстро и будет ничего не видно.
- Waterfall — это визуализация сигнала. Желто‑голубая каша из пикселей на графике — это как раз оно.
- QT GUI Time Sink рисует график зависимости сигнала от времени.
- Compex To Mag — блок преобразования комплексных чисел в числа с плавающей точкой. На входе у него синие значения, а на выходе оранжевые.
- Threshold — самый важный блок в нашей схеме демодуляции, он помогает отделить сигналы от остального шума. Я задал значения low 13m и high 13m — это амплитуды сигналов, которые я хочу отделить.
Как подбирается порог чувствительности
Чтобы найти порог для твоей SDR, придется собрать еще одну дополнительную схему. Справа в поиске найти блоки Peak Detector и Time Sink. В блоке Time Sink нужно выставить три входа, а если у Peak Detector отсутствует Debug port, то только два. После сборки схемы ты увидишь, на какой амплитуде будут пики полезного сигнала. - Symbol Sync — это еще один важный блок синхронизации символов. Выше я уже говорил, что выбрал частоту дискретизации 4 MSPS, и нужно это как раз для работы блока синхронизации, поскольку его минимальный параметр Samples per Symbol равен 2, а возможно это, только если частота дискретизации входного сигнала не меньше 4 MSPS. Если у тебя не такой крутой приемник (например, RTL-SDR) — не беда, можно отключить Symbol Sync и использовать блок Keep 1 in N (нарисован серым на схеме выше). С блоком синхронизации из сырой записи я в своем тесте получил 18 из 31 хороших пакетов, а без него — 11 из 29. Получается, что, просто используя нормальную синхронизацию, ты получишь значительно больше валидных данных.
- Float to Char — этот блок преобразует числа с плавающей запятой в символы и отправляет в File Sink.
- File Sink сохраняет байты в файл для дальнейшего анализа.

Самое первое — это наш Waterfall, на нем удобно глазами искать сигнал. Дальше идет Time Sink после синхронизации: тут два сигнала — красный (сигнал ошибки) и синий (исправленный по времени сигнал). Эти сигналы уже напоминают что‑то цифровое, но настоящий цифровой сигнал отображается уже на третьем графике (обработанный блоком Threshold). Четвертый график — это тот же исходный сигнал, что на первом графике, но обработанный блоком Threshold.
Анализ файла
После демодуляции файл будет выглядеть так.Код: Скопировать в буфер обмена
Код:
000717e0: 0000 0100 0100 0000 0000 0001 0000 0000 ................
000717f0: 0101 0000 0100 0000 0000 0101 0000 0100 ................
00071800: 0101 0001 0000 0100 0101 0000 0101 0001 ................
00071810: 0000 0101 0001 0001 0100 0101 0000 0100 ................
00071820: 0100 0100 0100 0101 0001 0001 0001 0000 ................
00071830: 0100 0100 0100 0100 0101 0000 0100 0100 ................
00071840: 0100 0001 0101 0000 0100 0100 0100 0100 ................
00071850: 0100 0100 0100 0100 0100 0100 0100 0100 ................
00071860: 0100 0100 0100 0100 0100 0100 0100 0100 ................
00071870: 0100 0100 0100 0100 0100 0100 0100 0101 ................
Python: Скопировать в буфер обмена
Код:
import requests
def read_binary_file(filename):
with open(filename, 'rb') as file:
return [int(byte) for byte in file.read()]
def find_pattern(data, pattern):
pattern_length = len(pattern)
matches = []
for i in range(len(data) - pattern_length + 1):
if data[i:i+pattern_length] == pattern:
matches.append(i)
return matches
Python: Скопировать в буфер обмена
Код:
def decode_adsb(bits):
decoded = []
for i in range(0, len(bits), 2):
if bits[i:i+2] == [1, 0]:
decoded.append(1)
elif bits[i:i+2] == [0, 1]:
decoded.append(0)
return decoded
Код: Скопировать в буфер обмена
Код:
data = read_binary_file("decoded2.bin")
pattern = [1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
matches = find_pattern(data, pattern)
print("Total matches: ", len(matches))
good = 0
bad = 0
Python: Скопировать в буфер обмена
Код:
for match_index in matches:
try:
start_index = match_index + len(pattern)
end_index = start_index + 224
end_index2 = start_index + 112
extracted_bits = data[start_index:end_index]
extracted_bits2 = data[start_index:end_index2]
decoded_bits = decode_adsb(extracted_bits)
decoded_bits2 = decode_adsb(extracted_bits2)
hex_value = hex(int(''.join(map(str, decoded_bits)), 2)).replace('0x','')
hex_value2 = hex(int(''.join(map(str, decoded_bits2)), 2)).replace('0x','')
if len(hex_value) == 28:
response = requests.get(f"http://jasonplayne.com:8080/decode?packet={hex_value}&refLat=&refLon=")
if "Failed to decode." in response.text:
bad += 1
else:
good += 1
print(response.text)
if len(hex_value2) == 14:
response = requests.get(f"http://jasonplayne.com:8080/decode?packet={hex_value}&refLat=&refLon=")
if "Failed to decode." in response.text:
bad += 1
else:
good += 1
print(response.text)
except:
pass
print("Total good/bad: ", good, "/", bad)
При хорошем раскладе ты увидишь примерно такой вывод:
Код: Скопировать в буфер обмена
Код:
8d89617999086e99b8480ab9e174
MODE S Packet:
Length : 56 bits
Frame : 8d89617999086e99b8480ab9e174
DF: Downlink Format : (17) ADS-B
CA: Plane Mode S Cap: (5) Level 2,3 or 4. can set code 7. is airborne
VS: Vertical status : Airborne
AA: ICAO : 896179
ME : ADSB Msg Type : (19) Airborne velocity
SUB: Sub Type : 1
Intent Change : false
IFR Capable : false
Nav Accuracy Cat : 1
heading : 151.88
Super Sonic? : No
velocity : 232.65
EW/NS VEL : (East/west: 109) (North/South: -204)
Vertical Rate : -1088
HAE Delta : 225 (Height Above Ellipsoid)
Надеюсь, и тебе понравилось погружение в интересный мир радиосигналов. Приятных исследований!
Источник xakep.ru
Автор @qeewqq
t.me/qeewqw