Эй, на борту!
Перехватываем и разбираем сигнал AIS — системы идентификации кораблей
Введение
AIS была создана давно, и ее главная цель — безопасное мореплавание. В настоящий момент система выполняет следующие функции:
- защита от столкновения судов;
- передача информации о корабле наземным станциям;
- контроль трафика судов через порты;
- слежка за судами для помощи в ЧП.
Применений у системы много. Например, люди, часто плавающие на своих яхтах, покупают маячки AIS, которые могут транслировать сигнал бедствия всем судам вокруг, если человек окажется за бортом или судно попадет в экстренную ситуацию.
AIS позволяет общаться с другими судами для обмена важной информацией. Такая технология помогает избежать аварий. Это особенно актуально для больших кораблей, которые не могут резко поменять курс или остановиться.
Для реализации AIS нужен транспортер, работающий в диапазоне VHF (134–174 МГц). Используя специальную систему разделенного доступа к каналу, SOTDMA, AIS может передавать до 4500 отчетов в минуту. Про SOTDMA мы поговорим чуть позже.
В реальных же условиях корабли не всегда находятся возле берегов и наземные станции не всегда могут получить данные о кораблях. Чтобы это исправить, в AIS добавили интеграцию со спутниковой связью. Эта система называется SAT-AIS, она есть на всех больших кораблях и стоит очень дорого, что делает ее недоступной для обычных судов. Чтобы исправить эту проблему, люди разработали систему, в которой суда без SAT-AIS могут использовать ближайшие корабли с SAT-AIS для передачи данных о себе.

Типы сообщений AIS
В зависимости от передаваемой информации сообщения могут иметь разную структуру. Чтобы не запутаться, в систему внедрили типы сообщений, первые 6 бит показывают тип и, соответственно, формат дальнейших данных. Немного углубимся в форматы сообщений и разберемся, какие данные можно передавать и получать в AIS.
Всего в AIS 21 основной тип сообщений, в будущем этот список может быть расширен до 63. Сообщения имеют разные форматы временного доступа к системе, разный приоритет и назначение. Рассмотрим все сообщения, разделив их на классы: сообщения передатчиков класса А, сообщения передатчиков класса Б, сообщения от ATON, бинарные сообщения AIS с адресом, бинарные сообщения AIS для всех приемников.
Сообщения передатчиков класса А
Позиция корабля
Сообщения передатчиков класса А с позицией передаются через равные промежутки времени от 2 до 10 с автоматически. Они содержат данные о текущей позиции корабля, его скорости, направлении, состоянии индикаторов маневров, в случае если корабль делает разворот или другой сложный маневр. Разберем формат сообщений типа 1, 2 и 3, которые отвечают за передачу позиции.

В целом ничего сложного, есть термины, которые используются только в корабельном деле, но общая суть должна быть ясна. С помощью этих типов сообщений строятся карты кораблей и отслеживаются их передвижения.
Статические данные о корабле
Статические данные могут включать в себя позывной, версию AIS, идентификаторы приемника и передатчика, тип судна, тип груза и еще кучу важных деталей. Эти сообщения относятся к типу 5, рассмотрим их структуру.

Сообщения со статической информацией транслируются каждые 6 мин.
Широковещательное сообщение
Сообщение типа 27, которое используется для передачи позиции (как в типах 1, 2 и 3), но имеет меньшее количество битов — 96 бит вместо 168 в типах 1, 2 и 3. Это позволяет транслировать сообщение на спутники или на более дальние расстояния без проблем.
Сообщения передатчиков класса Б
Сообщения передатчиков класса Б соответствуют форматам, описанным в классе А, но имеют немного другую бинарную структуру передаваемых сообщений. В связи с этими различиями сообщения этих передатчиков выделяют в отдельные типы. За передачу позиции отвечают сообщения типа 18 и 19, последнее является своеобразным легаси. Сообщение типа 24 содержит статическую информацию о корабле.
Сообщения ATON
Остановимся на формате сообщений ATON и проанализируем их более подробно, потому что это довольно интересно. ATON имеет только один тип сообщений — 27. Передаются эти сообщения автоматически через определенный промежуток времени.

Как видишь, в сообщении много разной интересной информации.
Бинарные сообщения
Бинарные сообщения имеют типы 6 для сообщений с получателем и 8 для широковещательных. Бинарные сообщения используются для передачи любой информации, например сообщений другим кораблям. Рассмотрим структуру бинарных сообщений типа 6, для типа 8 она похожа, просто отсутствует поле назначения.

Типы AIS
У системы множество применений, и, соответственно, есть множество устройств, где она реализована. Давай посмотрим, какие есть основные типы девайсов и чем они отличаются друг от друга.
Класс А
Это самые популярные передатчики для кораблей. Сигнал с позицией (тип 1, 2 и 3) автоматически транслируется каждые 2 с. Время передачи может меняться в зависимости от курса и скорости судна. Сигналы с дополнительной информацией, например с показаниями датчиков (тип 5), транслируются каждые 6 мин тоже автоматически. Передатчики этого типа позволяют кораблям обмениваться текстовыми данными. Также системы класса А могут принимать информацию о погоде от наземных станций. Больше информации можно найти в стандарте IEC 61993-2.
Класс Б
Станции этого типа намного слабее станций класса А, у них меньше и мощность, и число возможностей. Станции точно так же автоматически транслируют свое местоположение, но с большим интервалом и меньшей мощностью. Также они передают дополнительную информацию, но количество этой информации на порядок меньше. Устройства класса Б могут получать текстовые сообщения, но не могут их передавать. За подробностями обращайся к стандартам IEC 62287-1 и 62287-2.
Наземные станции
Наземные станции помогают синхронизировать информацию из разных источников и время передачи, а также передавать судам текстовые сообщения, например о надвигающемся шторме. Каждые 4 с наземная станция отправляет свой уникальный идентификатор (MMSI вида 00MIDXXXXX
) и данные о времени. Наземные станции также могут передавать данные для систем AIS ATON (AIS Aid to Navigation) и ASM (Application Specific Messages), которая передает точную информацию о прогнозе погоды. Больше информации — в стандарте IEC 62320-1.
SART
Поисково‑спасательные системы, которые используются в экстренных ситуациях как маяк для спасения. После активации транслирует сообщения типа 14 и позицию передатчика. Всего передается восемь сообщений в минуту. Передатчики спасательного типа можно определить по MMSI, который начинается на 970, 972 или 974. Передатчики SART транслируют по четыре сообщения на каждой из частот AIS, то есть четыре на 161,975 МГц и четыре на 162,025 МГц. Позиция передатчика определяется через встроенный приемник GNSS. Подробнее — в стандарте IEC 61097-14.
ATON
Навигационная система AIS Aid to Navigation позволяет кораблям, которые используют AIS, получать информацию о физических объектах в водах, например скалах или мелководье. Существует три основных ATON. Первый из них — физический объект, который транслирует информацию о ближайших физических объектах. Второй — синтетический, который не транслирует AIS, а просто с помощью света показывает местонахождение объектов. Обычно данные о синтетических ATON передаются с наземных станций. Третий тип — виртуальный, в данном типе информация об объектах передается только через наземные станции или спутники. Системы ATON можно обнаружить по MMSI, который начинается на 993XXXXX
. Подробности — в стандарте IEC 62320-2.

Подводим итоги
Как видно, в AIS много подсистем, которые отвечают за разные функции — начиная от передачи данных между кораблями и заканчивая спасательными объектами. Все они передают данные по незащищенному каналу, кроме, конечно, Blue Force Tracking, военной системы США и НАТО, которую они используют в зашифрованном виде через спутники. Атакующий может легко передать данные, например ATON, и заставить корабли развернуться или запустить еще один корабль, который будет идти прямо на цель. Все это возможно сделать с простым SDR-передатчиком за 200–300 долларов. В этой статье мы не будем углубляться в атаки на AIS, а только попробуем полностью разобраться в передаче, модуляции и кодировании.
warning
Статья имеет ознакомительный характер. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Отметим основные пункты:
- Данные о позиции AIS получает по GNSS.
- Данные о других кораблях система получает либо с наземных станций, либо непосредственно от других кораблей.
- Есть разные типы передатчиков.
- Типы передатчиков можно установить по MMSI.
- Некоторые корабли могут работать с AIS-SAT, а некоторые нет.
- Система не имеет шифрования, кроме как для военных частот.
- AIS работает на двух частотах или каналах (VHF): 161,975 МГц и 162,025 МГц с шириной в 25 кГц.
Изучить, как выглядит AIS, можно на официальном сайте системы.

Демодуляция
Перейдем к более интересной составляющей статьи. В этом разделе изучим модуляцию сигнала и основные форматы данных.
Частота
AIS работает на двух основных частотах. В некоторых источниках их называют каналами. Это 161,975 МГц и 162,025 МГц, каналы же соответственно называются 87b и 88b. Все это находится в диапазоне VHF, который включает в себя метровые волны от 1 до 10 м. Радиосвязь на этом диапазоне, как правило, возможна на расстояние до нескольких десятков километров, а при совпадении факторов ионизации и отражения и до тысяч километров — при наличии мощного передатчика. VHF отлично подходит для связи в городе и на местностях с прямой видимостью, какой воды и являются.
Модуляция
Для модуляции используется GMSK — это один из видов частотной модуляции, который передает данные, изменяя частоту при изменении бита. Например, если 1 — это 10 Гц, а 0 — 20 Гц, то в зависимости от исходных данных сигнал будет иметь разные частоты в разных временных промежутках.
GMSK — это улучшенная версия частотной модуляции. Так как большое количество передатчиков не должны мешать друг другу, GMSK имеет минимальную ширину спектра и хорошую скорость передачи. Это позволяет экономить место в полосе, причем сложность передатчиков и приемников не слишком возрастает.
В основе такой модуляции лежит гауссовский фильтр нижних частот, а индекс модуляции, который задает разницу между частотами для 0 и 1, минимален (0,5). Все это позволяет получить минимальную ширину спектра. Если хочешь подробнее изучить, как работает GMSK, можешь начать с моих статей про FSK, MSK и CPFSK.
Здесь же мы углубимся в частотную модуляцию, чтобы лучше понимать, что именно мы будем демодулировать.
GMSK
Рассмотрим несколько примеров работы GMSK-модуляции. Начнем с простого — с того, как модулируется сигнал. Начнем с FSK. Это самая простая частотная модуляция, которая без какой‑либо обработки переключает частоты в зависимости от входного сигнала. Обычно в схеме модуляции FSK есть два генератора с разными частотами и ключ.
На ключ подается либо 1, либо 0, в зависимости от передаваемых данных. На выходе получается сигнал с разными частотами. Длительность каждого бита выбирается исходя из требований к скорости передачи, но бесконечно уменьшать длительность сигнала не получится из‑за особенностей FSK.

Спектр FSK довольно широкий из‑за скачкообразного изменения фазы между переключениями частот. Эти скачки создают дополнительные боковые гармоники на спектре, которые не позволяют использовать FSK при маленьком канале. Чтобы решить эту проблему, была разработана CPFSK — частотная модуляция с непрерывной фазой.
Что такое фаза
Фаза — это положение текущего значения сигнала в пределах одного периода относительно определенной начальной точки.

CPFSK-модуляторы учитывают фазу прошлого сигнала и начинают переключение без скачка фазы.

Как видно на двух последних графиках, у CPFSK нет скачкообразного перехода, что позволяет существенно снизить количество боковых гармоник. Если изучить спектр двух модулированных сигналов — FSK и CPFSK, то разница становится еще очевиднее.

Заметно, что в CPFSK боковых гармоник почти нет, но проблема ширины канала все еще остается. Так как в частотной модуляции используется две частоты, то между этими частотами должна быть какая‑то разница, чтобы при приеме сигнала и его демодуляции можно быть отличить, где 0, а где 1.
Разница между частотами называется девиацией частот. При уменьшении девиации можно достигнуть порога, при котором сигнал уже нельзя восстановить. Модуляция с минимальной девиацией, а точнее, с минимальным индексом частотной модуляции называется MSK (Minimum Shift Key). Индекс модуляции в MSK составляет 0,5. Почему столько и как его получить, я писал у себя в блоге. При сравнении спектров CPFSK и MSK разница заметна.

Теперь, после того как изучены FSK, MSK и CPFSK, можно перейти непосредственно к GMSK. Это частотная модуляция, по сути MSK, к которой применили гауссовский фильтр нижних частот, что позволило еще сильнее уменьшить ширину спектра. Сравнить MSK и GMSK можно на следующем графике спектра.

Демодуляция GMSK
Не будем останавливаться на музейных частотных детекторах и детекторе отношений, рассмотрим более современный квадратурный демодулятор. Сигнал в квадратурных демодуляторах раскладывается на две ортогональные составляющие: синфазную (I) и квадратурную (Q). Сам процесс демодуляции включает несколько основных этапов, которые мы сейчас и рассмотрим.
При получении сигнал s(t) передается на два смесителя, где он умножается на два ортогональных сигнала: cos(
и sin(
, где wc — это угловая частота несущей. После умножения получается два сигнала:

Далее нужно отфильтровать нижние частоты. Для этого оба сигнала пропускаются через фильтры низких частот ФНЧ, чтобы удалить высокочастотные составляющие, оставляя только базовую полосу сигналов:

После обработки необходимо сформировать комплексный сигнал:

В GMSK информация передается через изменение частоты, а изменение частот приводит к непрерывным изменениям фазы. Следовательно, для демодуляции данных достаточно вычислить фазы двух сигналов. Начать стоит с детекции мгновенной фазы, для этого отделим мгновенную фазу сигнала r(t):

Теперь можно получить частотную девиацию, которая и будет показывать изменения частоты, а точнее, фазы.

T — период выборки.
Изменения разностной фазы, которые мы получили в конце, соответствуют передаваемым данным. Учитывая прошлое значение фазы, можно получить данные о текущем символе.
Хоть GMSK и изменяет частоту, изменение частоты напрямую изменяет фазу. Чистая частотная модуляция означает, что мгновенная фаза изменяется со скоростью, пропорциональной мгновенной частоте, следовательно, детектирование изменений фазы позволяет восстановить информацию из сигнала.
Слоты
Настало время поговорить о временных слотах в AIS. Как бы мы ни ужимали ширину спектра при передаче, канала все равно не будет хватать из‑за количества кораблей. Чтобы исправить это, в AIS интегрировали систему TDMA (Time Division Multiple Access), которая позволяет делить доступ к передаче по времени между судами. В AIS подразумевается ограниченное количество слотов. Для каждого канала выведено 2250 слотов каждую минуту, то есть 4500 слотов на оба канала.

Каждая система AIS автоматически адаптируется к количеству используемых слотов в конкретном регионе, это позволяет существенно снизить сложность приема. Бывает, все слоты перегружены, на этот случай приемники AIS запрограммированы таким образом, чтобы принимать данные от наиболее близких кораблей. Это сделано для избежания столкновений.
Как и во всех системах, у TDMA есть еще подсистемы, которые используются в разных случаях и в разных устройствах.
SOTDMA
Начнем с SOTDMA (Self Organised Time Division Multiple Access). Это самая сложная схема TDMA для доступа к AIS. В SOTDMA все станции должны иметь четкое и синхронизированное время. Это решается благодаря синхронизации по GNSS, что позволяет точно делить слоты во времени.
При передаче данных SOTDMA в пакете содержится информация о следующих передачах, это позволяет другим приемникам составлять карту слотов и эффективно выбирать для передачи свободные. Соответственно, важная особенность реализации передатчиков — это возможность выбирать свободный слот, чтобы не мешать другим. И, как следствие, каждая станция должна уметь перестраивать свои слоты под реалии текущего региона. В одной точке свободны будут одни слоты, а при переходе в другую будут уже совершенно другие.
SOTDMA разработана с учетом того, что наступит момент, когда свободных слотов не останется, тогда включается механизм повторного использования слота. Приемник в этом случае обязан принимать только сигнал ближайших кораблей. Все эти требования также оборачиваются наличием требований к оборудованию, таких как определенное количество оперативной памяти, мощность процессора и другие характеристики.
Подробнее — в стандарте ITU-R M.1371-4.
RATDMA
RATDMA — Random Access Time Division Multiple Access. Как понятно из названия, этот вид TDMA используется, когда нужно выбрать случайный слот. Этот метод нужен в основном сначала, когда передатчик только входит в регион, или же для передачи неповторяющихся сообщений, например текстовых данных. Как и в SOTDMA, требуется синхронизация по времени для всех устройств TDMA. Для синхронизации используется GNSS.
Передатчик с RATDMA выбирает по своей внутренней карте случайный слот, который не используется другой станцией. Он не анонсирует задействование этого слота, просто отправляет через него данные. Главное отличие RATDMA от SOTDMA — RA не анонсирует следующие передачи и слоты, что не позволяет другим станциям определить занятые слоты. Из‑за этой особенности RATDMA невозможно использовать для периодической передачи.
Подробнее — в стандарте ITU-R M.1371-4.
ITDMA
ITDMA — Incremental Time Division Multiple Access. Время здесь все еще синхронизируется по GNSS. Станции, использующие ITDMA, опираются на внутреннюю карту слотов и выбирают случайный свободный слот. После выбора устройство с ITDMA анонсирует передачу в выбранном слоте. ITDMA используется, когда станции нужно передать изменение во времени периодических передач или же анонсировать непериодическое сообщение, например текстовое сообщение, связанное с безопасностью. ITDMA не используется как отдельная схема для доступа в систему AIS, в основном она дополняет SOTDMA. Главное отличие от RATDMA — в анонсировании передачи.
Подробнее — в стандарте ITU-R M.1371-4.
FATDMA
FATDMA — Fixed Access Time Division Multiple Access. Система похожа на обычную SOTDMA, но отличается тем, что данные о слоте загружены напрямую в передатчик, то есть слоты всегда статичны для любого случая. Как и в прошлых схемах, требуется синхронизация времени по GNSS. При входе в регион станции FATDMA транслируют сообщение о своих слотах, чтобы другие станции могли знать, какие из них заняты. Из‑за статичных слотов использование FATDMA стараются свести к минимуму, чтобы не мешать динамической работе AIS.
Подробнее — в стандарте ITU-R M.1371-4.
CSTDMA
CSTDMA — Carrier Sense Time Division Multiple Access. В данном случае синхронизация с временем выполняется не по GNSS, так что система связи с GNSS в CSTDMA не нужна. Станции, использующие CSTDMA, непрерывно следят за каналами AIS, чтобы находить свободные слоты и использовать их. Если станция CSTDMA видит, что никто не использует слот, она отправляет данные и отключает передачу на 30 с, после этого повторяет все шаги. Важно заметить, что станции этого типа не могут анонсировать слоты. Они не требуют сложных компонентов и используются на маленьких судах.
Подробнее — в стандарте ITU-R M.1371-4.
PATDMA
PATDMA — модифицированная версия SOTDMA, разработанная специально для систем, которые могут только транслировать данные, например SART. Время синхронизируется по GNSS. Каждые 8 мин станция выбирает случайный слот для передачи, это делается для того, чтобы увеличить шансы быть услышанной. В самой передаче восемь пакетов данных, которые содержат разные данные.
Подробнее — в стандарте ITU-R M.1371-4.
Устройства и их совместимость с типами TDMA
Перейдем к связи типов и устройств. Общую информацию можно получить, изучив картинку ниже.

Класс А
Устройства класса А, как самые дорогие и технически сложные, могут использовать три самые сложные схемы доступа к слотам: SOTDMA, RATDMA и ITDMA. SOTDMA используется почти для всех периодических сигналов, например данных о позиции. RATDMA и ITDMA используются при входе в новый регион для начальной передачи и резервации слотов. RATDMA также используется для передачи коротких сообщений. ITDMA используется для анонсирования изменений в передаче.
Класс Б
В устройствах класса Б можно заметить CS и SO, это два разных типа, которые расшифровываются как Carrier Sense и Self Organising соответственно. CS могут использовать только CSTDMA, а SO используют схемы доступа класса А, но с некоторыми ограничениями в мощностях.
Наземные станции
Наземные станции используют FATDMA и RATDMA. Слоты FATDMA настраиваются отдельно и передаются другим приемникам с помощью анонсов. RATDMA используется для передачи коротких непериодических сообщений.
ATON
ATON работают с FATDMA и RATDMA, в зависимости от начальной конфигурации устройства. ATON первого типа работают только с FATDMA. Такая схема доступа требует наличия рядом наземной станции, которая будет анонсировать слоты для ATON. ATON третьего типа может как принимать, так и передавать данные, так что для передачи данных подойдет RATDMA или FATDMA.
SART
Спасательные передатчики SART используют только PATDMA.
Форматы и кодирование сигналов
Про слоты мы уже поговорили, теперь необходимо определиться с форматом и типами сообщений в AIS. Для начала отмечу, что длительность каждого слота в передаче — 26,66 мс. Можно определить максимальную длину сообщения для скорости 9600 бит/с.

При округлении получаем ровно 256 бит информации на каждый слот. Но сообщения на самом деле могут быть длиннее и занимать до пяти слотов, в таком случае флаг окончания будет передан только через время, которое будет больше 26,66. Перед отправкой такого большого сообщения передатчик должен сообщить о нем.
Перейдем непосредственно к формату сообщения. Оно модулируется в GMSK, а значит, при демодуляции мы получаем последовательность битовых данных. Это не случайная последовательность.

Разберем поля основного сообщения и данных.
- Ramp Up — стабилизация передатчика и отсчетов.
- Preamble — преамбула сообщения, которая необходима для определения начала. Это последовательность битов, которая одинакова для каждой передачи. В бесконечном потоке нулей и единиц помогает найти начало сообщений.
- Start Flag — начало данных, флаг, который указывает, что дальше находятся данные.
- Data Message — данные сообщения.
- FCS — проверка целостности сообщения, его хеш.
- End Flag — конец данных, указывает, что дальше данных нет.
- Buffer — используется для NRZI, битовых вставок, синхронизации приемников и других внутренних обработок.
Важно упомянуть, что AIS работает с кадрами протокола HDLC (High-Level Data Link Control). Это протокол канального уровня сетевой модели OSI.
Формат HDLC работает с флагами «стоп» и «старт», и у них есть специальные последовательности. Например, 01111110 — это сигналы «старт» и «стоп». Но что, если такая последовательность встретится в самих данных AIS? Чтобы этого избежать, после пяти единиц вставляют один ноль, что позволяет разорвать такие последовательности. Так как NRZI — это основа передачи в AIS, разберемся с ним подробнее.
NRZI
NRZI (Non Return to Zero Invertive) — способ кодирования данных для передачи через канал. Битовая последовательность превращается в код, в котором не будет длинных непереходящих сигналов, например десяти единиц или нулей подряд. Это необходимо для того, чтобы приемник всегда понимал, когда изменяется сигнал, и корректно мог принять любое сообщение, не сбиваясь. Как работает NRZI, видно на следующей картинке.

Если обобщить кодирование, то получается следующее правило: логическая единица представляется изменением уровня сигнала, а логический ноль представляется отсутствием изменения уровня сигнала.
Возьмем простой сигнал с картинки: 0101. Для его кодирования в NRZI необходимо начать с самого начала. Первый у нас 0, значит, в NRZI-кодировании это будет низкий уровень сигнала, так как изменения нет. Дальше идет 1, уровень сигнала NRZI уже высокий, так как произошло изменение. Затем идет 0, и уровень сигнала остался высоким, так как следующий символ оказался 0, а изменения требует только единица. Ну и последний символ — 1 требует изменения сигнала, поэтому в конце будет низкий уровень.
На примере кода 11111 видно, что сигнал всегда изменяется, так как единица всегда требует изменения сигнала. Декодировать NRZI можно, сравнивая прошлое и текущее состояние сигнала. Важно учесть, что перед отправлением пакета AIS он весь кодируется с помощью NRZI, даже преамбула.
Алгоритм декодирования NRZI можно проанализировать в коде GNU AIS, там показан самый примитивный и эффективный вариант.
for (i = 0; i < len; i++) { out = filtered[i]; curr = (out > 0); if ((curr ^ rx->prev) == 1) { // Детектирование пересечения нуля if (rx->pll < (0x10000 / 2)) { rx->pll += rx->pllinc / INC; } else { rx->pll -= rx->pllinc / INC; } } rx->prev = curr; rx->pll += rx->pllinc; if (rx->pll > 0xffff) { /* slice */ bit = (out > 0); /* nrzi decode */ b = !(bit ^ rx->lastbit); /* feed to the decoder */ protodec_decode(&b, 1, rx->decoder); rx->lastbit = bit; rx->pll &= 0xffff; } }
Авторы детектируют пересечение нуля и декодируют сообщение на основе прошлых значений. Также тут учтено несколько особенностей. Если пересечение нуля происходит раньше чем 1/2 периода символа, то период в rx->pll расширяется на 1/16 от периода семплирования, а если случается наоборот, то период уменьшается. Такой алгоритм сам себя подстраивает, что довольно эффективно.
Bit stuffing
Итак, раньше упоминалось, что при передаче данных в AIS могут встретиться системные последовательности. Например, в теле сообщения может появиться последовательность Stop Flag, которая означает конец передачи, но на самом деле ею не является. Чтобы избежать таких проблем, была разработана система, которая добавляет нули в специальные места сообщения, тем самым сбивая последовательности единиц. Выглядит это следующим образом: если в битовом потоке будет больше пяти единиц, то после них должен быть добавлен ноль.
0011111101011 — исходные данные
0011111[0]101011 — данные с bit stuffing
Как видно в примере, ноль разорвал непрерывные единицы. Как работают декодеры с bit stuffing, можно также изучить на примере исходного кода GNU AIS.
case ST_DATA: if (d->bitstuff) { if (in[i] == 1) { d->state = ST_STOPSIGN; d->ndata = 0; DBG(printf("%d", in[i])); d->bitstuff = 0; } else { d->ndata++; d->last = in[i]; d->bitstuff = 0; } } else { if (in[i] == d->last && in[i] == 1) { d->antallenner++; // Если на счетчике уже 4 (5), то выставляем bitstuff в 1 if (d->antallenner == 4) { d->bitstuff = 1; d->antallenner = 0; } } else d->antallenner = 0; DBG(printf("%d", in[i])); d->buffer[d->bufferpos] = in[i]; d->bufferpos++; d->ndata++; if (d->bufferpos >= 449) { protodec_reset(d); } } break;
Тут обрабатывается два варианта: в первом случае последовательность единиц расценивается как обычные данные, если после пяти единиц идет ноль. В другом варианте если после пяти единиц идет единица, то последовательность считается стоп‑флагом и чтение фрейма останавливается.
NMEA и формат передачи
Системы AIS могут передавать данные как внутри корабля, например от датчика к главной системе, так и между кораблями и другими объектами. Данные от приемника AIS и от датчиков корабля передаются в формате NMEA 0183, это стандарт связи для морского оборудования. Данные в этом формате можно получить, подключившись к терминалу AIS. Важно заметить, что этот формат не используется в передаче, при приеме приемник конвертирует бинарные данные в NMEA.
Данные в таком формате выглядят следующим образом:
!AIVDM,1,1,,A,155uT`0000Su4vt>MGIUPH4d08<Q,0*02
Все символы в сообщении всегда должны быть в читаемом диапазоне. Разберем формат NMEA.
-
!
— тип сообщения,AIVDM !
— для данных, полученных с другого устройства,AIVDM !
— данные с датчиков корабля;AIVDO -
1
— количество данных, для некоторых сообщений нужно больше 1, максимум 9; -
1
— номер сообщения, если их несколько; - пропуск — идентификатор сообщения, если их несколько;
-
A
— канал AIS, A или B; -
155uT'0000Su4vt>
— данные AIS в AIS-ASCII6;MGIUPH4d08< Q -
0*
— конец данных; -
02
— чек‑сумма.
Формат сообщения NMEA понятен, но в самом сообщении NMEA есть и другие свойства, такие как тип сообщения, идентификатор передатчика, зарезервированные под bit stuffing поля и состояние репитера. Длина сообщения NMEA тоже может варьироваться. Чтобы ты лучше понял структуру составных сообщений, приведу пример сообщений с разными номерами, но относящихся к одному предложению.
!AIVDM,2,1,1,,59@>k542E5M@CH7?CC@aT4pG:2222222222222167P9785@e000c@@PPDp888,0*66
!AIVDM,2,2,1,,8888888880,2*5c
Как видно, у этих сообщений в поле «Количество данных» стоит 2, номер сообщений разный, а идентификатор — один, так как они оба относятся к одному сообщению.
Поговорим о том, как расшифровать сообщение NMEA для его обработки. Выглядит сообщение как набор случайных символов, но на самом деле оно закодировано с использованием AIS-ASCII6. AIS-ASCII6 — это таблица, где каждый символ означает определенный набор битов.

Первый шаг для декодирования — перевод всех символов в их бинарное представление. Если мы возьмем первое сообщение, то 155 из его начала можно представить как 000001 000101 000101. Первые 6 бит сообщения, то есть первый символ, показывают тип сообщения, в данном случае это 000001 — первый тип. Всего известно 27 типов сообщения, все их перечислять нет смысла, можно посмотреть в документе на сайте allaboutais.com (PDF). Основные типы — это 1, 2 и 3, которые отвечают за автоматическую передачу позиции.
Следом идут 2 бита типа повтора, то есть сколько раз сообщение будет повторяться. 0 — обычное интервальное сообщение, 3 — сообщение больше не будет повторяться. Следом — номер MMSI, уникальный идентификатор оборудования, по которому можно определить тип передатчика и другие особенности.
Это основные поля, которые всегда есть во всех сообщениях. Остальные поля могут меняться в зависимости от типа сообщения, ты можешь изучить их в документах по AIS. В общем случае передача транспондеров класса А с данными о позиции имеет структуру, описанную в начале статьи. Эта структура используется при передаче.
На этом углубляться в форматы закончим и перейдем непосредственно к записи и изучению реальных сигналов.
MSB и LSB
Перед кодированием и демодуляцией поговорим вот об этом пункте в документации:
When data is output on the VHF data link it should be grouped in bytes of 8 bits from top to bottom of the table associated with each message in accordance with ISO/IEC 13239:2002. Each byte should be output with least significant bit first. During the output process, data should be subject to bit-stuffing (see § 3.2.2) and NRZI coding (see § 2.6).
То есть при приеме данных с VHF необходимо сгруппировать данные по 8 бит в байты и вывести их, начиная с LSB. Разница между LSB и MSB хорошо показана на следующей картинке.

Следовательно, нужно конвертировать вывод данных из MSB в LSB после приема и, соответственно, в MSB из LSB при передаче. Это важно учитывать. Также можно найти интересный код в GNU AIS, который авторы почему‑то обозначили как /
. Этот код как раз и отвечает за конвертацию MSB в LSB перед проверкой CRC.
/* what is this? */ buf = (unsigned char *) hmalloc(sizeof(*buf) * buflen); for (j = 0; j < buflen; j++) { tmp = 0; for (i = 0; i < 8; i++) tmp |= (((d->buffer[i + 8 * j]) << (i))); printf("tmp: %d\n", tmp); buf[j] = tmp; } /* ok, here’s the actual CRC calculation */ unsigned short crc = protodec_sdlc_crc(buf, buflen); //DBG(printf("CRC: %04x\n",crc)); /* what is this? */ memset(d->rbuffer, 0, DEMOD_BUFFER_LEN); for (j = 0; j < length_bytes; j++) { for (i = 0; i < 8; i++) { x = j * 8 + i; if (x >= DEMOD_BUFFER_LEN) { hlog(LOG_ERR, "protodec_calculate_crc: would run over rbuffer length"); hfree(buf); return 0; } else { d->rbuffer[x] = (buf[j] >> (7 - i)) & 1; } } }
Сначала в цикле все группируется в байты, потом, после проверки CRC, обратно в биты уже в нужном порядке вывода. В массиве rbuffer
уже правильная последовательность, которую можно парсить по структуре, описанной выше.
Кодирование сигнала
Остановимся на кодировании сигнала, чтобы систематизировать схему. Первоначально у нас есть какая‑то информация, далее кодируем ее для передачи и декодируем после приема. Общая схема кодирования таких данных для передачи AIS выглядит так: BIN → MSB/LSB → BIT STUFFING → NRZI → GMSK.
Схема для приема будет следующей: GMSK → NRZI → BIT STUFFING → LSB/MSB → BIN → NMEA.
Записываем сигнал
Наконец‑то после небольшого ликбеза, который, кстати, еще можно много чем дополнить, переходим к практике. Начать стоит с записи сигнала, который мы будем исследовать. Лучше всего записывать сигнал где‑то в ближайшем порту, там можно получить данные не только с кораблей, но и с наземных станций. Для записи можно использовать разные средства, начиная от HackRF PortaPack и заканчивая дорогими SDR. Я использую в своих экспериментах BladeRF, так что все действия будут в основном описаны для этого SDR. Мой опыт ты можешь легко спроецировать на HackRF и RTL-SDR. Давай соберем в GNU Radio схему для записи сигнала с двух каналов AIS в файл.

Схема состоит из четырех основных элементов, два из которых отвечают за вывод информации на экран. Начинается все с Osmocom Source, где в качестве аргумента передано bladerf=0
, что дает блоку понять тип источника, в данном случае это BladeRF. Частота на нулевом канале выставлена в 162 МГц, а ширина канала — в 200 кГц. Частота семплирования (sample rate) в моем случае 2 MSPS, минимальное же значение для AIS находится где‑то около 48 тысяч, но советую брать 1 MSPS как стандартное значение.
Такие настройки позволяют записать сразу оба канала, в будущем мы разделим их на два отдельных файла для анализа. Блок File Sink отвечает за сохранение данных в файл. Два других блока — Frequency Sink и Waterfall Sink — помогают понять, верно ли идет запись сигнала. При правильной настройке и хорошей антенне ты должен находить следующие сигналы на Waterfall.

На изображении видны сигналы слева и справа от нулевой частоты, это и есть наши данные AIS с двух каналов. Когда данных наберется достаточно, остановить запись можно будет, закрыв окно с водопадом, или же напрямую из GNU Radio, нажав кнопку Stop.
Демодуляция
Для демодуляции и декодирования AIS есть множество проектов на GitHub и на форумах, посвященных радио. Все такие проекты работают довольно просто: нужно либо подключить твой SDR, либо запустить записанный файл. Все это не очень интересно. В этой статье мы попробуем сделать демодулятор в GNU Radio, конвертировать данные из IQ-сигнала в IQ-файл для GNU AIS и изучим, как работает SDRangel, на примере демодуляции и декодирования AIS.
SDRangel
SDRangel — это программа, созданная для управления SDR-устройствами. В ней можно принимать, демодулировать, декодировать, анализировать самые разные сигналы. Программа удобная и работает на всех системах.

Преобразование IQ в WAV
Перед изучением нашей записи в SDRangel необходимо преобразовать ее в формат либо WAV, либо SDRIQ. SDRangel работает только с этими двумя форматами. Самый простой вариант — преобразовать исходный файл RAW IQ из GNU Radio в двухканальный WAV. В первом канале будет реальная часть комплексного числа, а во второй — мнимая. IQ-файл состоит только из комплексных чисел, так что перед сохранением их нужно разделить.
Используем следующую схему для GNU Radio.

После запуска должен появиться WAV-файл. В блоке Wav File Sink нужно выбрать два канала, так как сохранять мы собираемся именно в два канала. Блок Complex To Float преобразует комплексное число в re и im (реальную и мнимую части) и передает их в каналы WAV-файла. Теперь можно перейти непосредственно к SDRangel.
Демодуляция и декодирование AIS
Для начала работы можно использовать подготовленный специально для AIS рабочий стол SDRangel. Найти его можно на вкладке Prefereneces → Configurations → AIS. Опять же это не очень весело и познавательно, поэтому сделаем все с нуля. Для начала нужно добавить источник сигнала. Это делается с помощью кнопки Add RX Device. Далее выбираем источник File Source и нажимаем «Добавить».

После этого на рабочем пространстве появится два окна, одно с управлением источников, а второе — с его визуализацией. Для добавления нашего файла в источник нажимаем на кнопку с изображением файла и выбираем WAV-файл. Теперь при запуске во втором окне должно появиться изображение водопада для нашего файла.

Теперь к уже готовому источнику можно подключить демодуляторы для AIS. Так как у нас файл с двумя каналами, нам нужно добавить два демодулятора для двух разных частот: один для –25 кГц, второй — для +25 кГц. Сделать это можно, нажав кнопку Add Channels в блоке, где ты выбирал файл.
Далее в меню выбираем AIS Demodulator и так делаем два раза. На экране появятся два новых экрана, которые можно разместить на рабочем пространстве как угодно. После добавления двух демодуляторов нужно настроить сдвиг частоты для каждого. У одного ставим -25000, а у второго 25000. В итоге должно получиться что‑то следующего вида.

Как видно на скриншотах, SDRangel уже успешно демодулировал и декодировал несколько сообщений AIS. Так как SDRangel не поддерживает все виды сообщений, не мешало бы получить их в сыром виде для дальнейшей обработки. Этим мы и займемся с помощью GNU Radio.
GNU Radio
Самое интересное, изюминка и жемчужина статьи — демодуляция в GNU Radio. Без использования дополнительного программного обеспечения, без готовых демодуляторов с GitHub и так далее. Только базовые блоки GNU Radio!
Исследуем сигнал
Вспомним, что в файле записаны сразу два канала AIS, следовательно, если мы хотим демодулировать их одновременно, нужно сдвинуть демодулятор в две разные стороны, желательно отфильтровать часть шумов. Для таких манипуляций в GNU Radio есть блок с названием Frequency Xlating FIR Filter, что можно перевести как частотно‑сдвигающий КИХ‑фильтр (фильтр с конечной импульсной характеристикой). По названию понятно, что этот вид фильтров может и сдвигать, и фильтровать сигнал. Также этот блок может ресемплировать сигнал, нам это необходимо.
Далее нужно еще более точно ресемплировать сигнал для точной GMSK-демодуляции, делаем это с помощью блока Rational Resampler. Нам нужны оба блока для ресемплирования, если мы хотим получить сложное число семплов для точного GMSK-демодулирования.
После сдвига и фильтрации можно переходить непосредственно к демодуляции, в GNU Radio есть отдельный блок для GMSK — GMSK Demod, но для квадратурных модуляций можно использовать также Quadrature Demod. Так как после GMSK у нас будет код NRZI, его тоже можно сразу декодировать в GNU Radio, это стало возможно в недавних версиях.
Разберем теперь три основных блока: FIR Filter, Rational Resampler и GMSK Demod.
Frequency Xlating FIR Filter

В самом фильтре есть пять основных параметров:
- тип входных данных;
- децимация для ресемплирования;
- taps, или вектор преобразования;
- сдвиг частоты;
- частота семплирования исходного сигнала.
Если мы хотим использовать этот фильтр не только для сдвига и децимации, необходимо добавить вектор преобразования. Значение в поле децимации используется как знаменатель для ресемплирования. Например, если исходная частота семплирования была 2 000 000, то при значении 20 на выходе мы получим 2 000 000/20 = 100 000. В примере настройки на скриншоте центральная частота стоит -25e3, что значит –25 на 10 в степени –3. Это сдвиг на первый канал AIS.
Изучим taps и визуальный пример работы фильтра.

На картинке видно, что фильтр сдвигает сигнал на нулевую частоту, при этом фильтруя его. Но фильтрует он очень хитро — с помощью вектора преобразования, который в нашем случае будет выглядеть следующим образом.
firdes.low_pass(1, samp_rate, 15000, 20000, window.WIN_HAMMING, 1)
Это фильтр нижних частот, который выглядит как вызов функции. Для объяснения его работы изучим его аргументы. Первым идет коэффициент усиления; так как усиливать ничего не нужно, он указан как 1. Далее — частота семплирования в виде переменной. Два следующих аргумента — частота среза и ширина переходной области, в данном случае частоты ниже 15 000 будут пропускаться, а частоты выше — подавляться.
Ширина переходной области — это ширина области, в которой фильтр переходит от пропускания к подавлению. Далее идет оконная функция, в нашем случае это окно Хэмминга. Последний аргумент не играет роли для Хэмминга, но отвечает за форму окна для других оконных функций. Оконные функции используются для сглаживания спектров, за счет сглаживания краев данных при обработке сигналов.
Rational Resampler

Следующий важный для ресемплирования блок — Rational Resampler. Чтобы получить более точную частоту семплирования, например если нужно целое число выборок на символ (как в нашем случае), простым делением иногда не обойтись. У Rational Resampler есть два параметра: интерполяция и децимация. При ресемплировании сигнала исходная частота семплирования сначала умножается на интерполяцию, а потом делится на децимацию. Таким образом можно вычислить и подогнать частоту под наши нужды.
GMSK Demod

Это главный блок, который отвечает непосредственно за демодуляцию и синхронизацию сигнала. На самом деле этот блок состоит из квадратурного демодулятора и синхронизации символов для восстановления их паттернов. Квадратурную демодуляцию я рассмотрел выше, и мы еще о ней поговорим при составлении схемы для GNU Radio.
Основные параметры это Samples/Symbol — количество выборок на символ, именно под этот параметр мы подгоняли частоту семплирования и параметр Gain Mu, который отвечает за саму демодуляцию и подбирается опытным путем. Как видно, на входе у этого блока комплексные числа, а на выходе получаем уже демодулированные биты, которые можно либо сохранить в файл, либо обработать.
Схема для GMSK Demod
Давай соберем простую двухканальную схему для демодуляции AIS на основе GMSK Demod.

Схема читается слева направо. Начальный блок File Source читает данные из ранее записанного файла. В настройках блока я указал Repeat: Yes, чтобы файл повторялся после конца. Далее идет разделение на два канала, с помощью КИХ‑фильтров. Первый фильтр дает смещение на –25 кГц, а второй на +25 кГц. Добавлю, что начальная частота семплирования была 2 000 000 выборов в секунду, но после КИХ‑фильтров с дециматором 20 она равна 100 000, так как 2 000 000/20 = 100 000.
Далее идет ресемплер, наша задача — получить более двух выборок на символ в GMSK-демодуляторе. Скорость передачи данных в AIS — 9600 бит/с, то есть для минимальной работы GMSK-демодулятора нам нужно 9600 * 2 = 19 200 семплов в секунду. Для лучшей работы я опирался на 9600 * 4, то есть 38 400.
Чтобы получить такое ровное число на выходе, нужно найти решение уравнения следующего вида:

Подставляя эти коэффициенты, получим нужное количество семплов на символ в GMSK Demod. Сам блок GMSK Demod я опытным путем настроил на значение 500e-3 для Gain Mu. Если будешь собирать свою схему, попробуй значения от 300e-3 до 500e-3, пока не начнет появляться преамбула и стартовый флаг. Оба эти параметра и методы отладки я опишу ниже.
После блока GMSK Demod в каждом канале добавлен блок для сохранения данных до декодирования NRZI, потом идет блок декодирования NRZI и опять сохранение файла. Это было сделано для анализа работы декодера NRZI.
Методы отладки
Так как любая схема требует отладки, рассмотрим настройку этой схемы с использованием простого скрипта на Python и любого текстового редактора. Для отладки внимательно пересчитываем Sample Rate до GMSK Demod и проверяем параметр выборок на символ в GMSK Demod. Следующий шаг — подбор верного значения Gain Mu, для этого нужно несколько раз демодулировать файл с разными значениями от 300e-3 до 500e-3 и изучить содержимое вывода. Так как на выходе получается бинарный файл и искать по нему в текстовом документе неудобно, я разработал скрипт, конвертирующий файл в текстовый формат.
#!/usr/bin/python3import argparsedef read_bits_from_file(file_path): with open(file_path, 'rb') as file: byte = file.read(1) while byte: if byte == b'\x00': yield 0 elif byte == b'\x01': yield 1 else: exit(1) byte = file.read(1)def main(): parser = argparse.ArgumentParser(description='Process a binary file') parser.add_argument('file_path', type=str, help='Path to the binary file') args = parser.parse_args() bit_stream = read_bits_from_file(args.file_path) with open('result_conversion', 'a') as f: for bit in bit_stream: f.write(str(bit))if __name__ == '__main__': main()
После конвертации файла с демодулированными значениями важно вспомнить структуру сообщений в AIS. Важные ее компоненты — преамбула и стартовый флаг, которые всегда равны одному значению. Я рекомендую использовать именно преамбулу и стартовый флаг вместе. Из‑за того что преамбула — это последовательность повторяющихся символов, иногда ее можно найти даже в шумах. Итак, преамбула — это 24 бита, выглядят они вот так:
010101010101010101010101
Стартовый флаг — 8 бит:
01111110
Если соединить оба этих значения, то получим следующее значение:
01010101010101010101010101111110
Открываем конвертированный файл и пытаемся найти в поиске нашу последовательность. Если нашел, значит, Gain Mu и другие параметры подобраны верно.

Также ты можешь конвертировать значения преамбулы из стартового флага в код NRZI онлайн и найти их в RAW-файле, который был создан до NRZI-декодирования.
Запускаем
Настало время запустить схему и изучить вывод. Для этого нажимаем на кнопку запуска в меню GNU Radio и наблюдаем водопад и сам сигнал. Форму сигнала до и после демодуляции изучим в схеме с квадратурным демодулятором, так как у нас в данном случае нет полного контроля демодуляции.
После запуска должна появиться следующая картинка и файлы с нашими данными.

Важно уточнить, что в этой схеме нет блока Throttle, который замедляет обработку. Без него сигнал обработается намного быстрее того времени, которое он должен был бы идти, так что водопад может оборваться быстрее, чем ты ожидаешь. Чтобы это исправить, добавь блок Throttle после File Source. Схема в данном случае уже отлажена, и мы можем изучить вывод файла, как это было показано в примере с отладкой.
Ты можешь попробовать расшифровать любой фрейм по описанию выше. Но для простой проверки можно использовать тип передаваемого сигнала, это первые 6 бит после стартового флага. Дальнейшее декодирование возможно только после удаления bit stuffing, а именно одного нуля после пяти единиц.
Нужно убирать нули до последовательности конца сигнала (она выглядит как стартовый сигнал). Пример удаления bit stuffing показан ниже.
Исходный сигнал:
01010101010101010101010101111110001000011000111000101010111010010100000100000100000001111000000010111111011010101111110
Преамбула:
010101010101010101010101
Стартовый флаг:
01111110
Данные и хеш‑сумма:
00110000000001011100100011110110100011110000001000000000000011101011111[0]11000010011110101011100001010111001000010011011111[0]101001011011000001000101100000011100010010110000011100110101100
Флаг окончания сообщения:
01111110
Выделим нули, вставленные с помощью bit stuffing:
00110000000001011100100011110110100011110000001000000000000011101011111[0]11000010011110101011100001010111001000010011011111[0]101001011011000001000101100000011100010010110000011100110101100
Убираем их:
0011000000000101110010001111011010001111000000100000000000001110101111111000010011110101011100001010111001000010011011111101001011011000001000101100000011100010010110000011100110101100
В конечном счете получаем битовые данные без bit stuffing, готовые к декодированию. Не забываем про LSB и MSB: конвертируем только первый байт в LSB, чтобы получить тип сообщения. Узнаем тип сообщения, то есть первые 6 бит:
00110000 -> [000011]00
При переводе 000011 в десятичную систему получаем 3, то есть тип сообщения 3, а это передача позиции судна.
Схема для Quadrature Demod
Схема с GMSK Demod имеет неприятную особенность: в ней нет полного контроля над демодуляцией. Так как это цельный блок, мы не можем отдельно настроить синхронизацию символов и демодуляцию. Чтобы исправить это, можно перейти к более низкоуровневым блокам: Quadrature Demod и Symbol Sync. Оба этих блока — часть GMSK Demod, но их использование позволит нам более детально изучить процесс демодуляции.
Разберем следующую схему.

Схема создана только для одного канала, начало соответствует GMSK Demod, КИХ‑фильтр и ресемплер настроены соответствующим образом. Схема выглядит иначе, начиная с блока Quadrature Demod, который отвечает непосредственно за квадратурную демодуляцию.
Благодаря полному контролю над демодуляцией с помощью блоков Time Sink мы можем изучать, как выглядит сигнал после демодуляции и как он выглядит после синхронизации символов. Для этого необходимо включить в настройках Time Sink панель управления, чтобы можно было изменять характеристики блока прямо во время его работы. Рассмотрим сигнал после демодуляции в блоке Quadrature Demod.

Как видно, после демодуляции сигнал становится похожим на что‑то читаемое и декодируемое. Для более точной демодуляции необходимо синхронизировать начало и конец битов, для этого используется блок Symbol Sync. Давай глянем его вывод.

У сигнала после синхронизации другой вид, так как количество выборов было уменьшено с 4 до 1, но со своей задачей блок справился. Теперь символы синхронизированы по времени и можно передавать вывод в блок Binary Slicer, который, используя специальные алгоритмы, превратит этот сигнал в битовую последовательность и сохранит в файл.
Методы отладки
Эту схему отладить тяжелее, чем с GMSK Demod, так как в ней больше параметров. Основной принцип отладки — изменение Gain у Quadrature Demod и изменение алгоритмов Symbol Sync. Это позволит нам получить правильную синхронизацию.
Запуск
После запуска получаем файл 88_quadra
, который конвертируем в текстовый и методом из GMSK Demod проверяем, есть ли там преамбулы со стартовым флагом.
GNU AIS
Так как декодировать руками биты — сложная задача, перейдем к программам, которые могут сделать это за нас. GNU AIS — это свободный софт, который позволяет декодировать двухканальный AIS-сигнал из файлов или напрямую из источников. Но прежде чем использовать эту программу, необходимо конвертировать наш файл RAW IQ.
Преобразование формата
Для преобразования формата я нашел схему для GNU Radio. В ней нужно будет пересчитать ресемплеры, ты можешь сделать это по аналогии с GMSK Demod. Автор схемы конвертации — Александру Чете.

В работу схемы вдаваться нет смысла, так как все блоки и принципы мы уже изучили. После запуска сохраняем файл aisfifo
и переходим к установке GNU AIS.
Установка
GNU AIS — старый опенсорсный проект, который не собирается на новых устройствах. Чтобы исправить эту проблему, нужно немного изменить исходный код, но для начала подготовим все необходимое.
Первое, что нужно сделать, — клонировать GNU AIS и установить MySQL. Установку MySQL я описывать не буду, так как для этого есть куча гайдов. Остановимся на GNU AIS.
git clone https://github.com/rubund/gnuais
cd gnuais/
Перед сборкой нужно немного исправить код, а конкретно файл ./
, в котором нужно заменить вот этот код:
struct mysql_state_t {
вот этим:
extern struct mysql_state_t {
Теперь можно переходить непосредственно к сборке проекта.
apt install build-essential libasound-dev libcurl4-openssl-dev libmysqlclient-dev cmake pkg-config
cmake .make
Как настроить базу данных, описано в create_table.
. Также необходимо будет указать логин и пароль для базы данных в файле gnuais.
. После сборки появится файл ./
, который, собственно, нам и нужен.
Декодирование AIS
Копируем файл aisfifo
куда‑нибудь, где он будет доступен GNU AIS, и запускаем следующей командой:
./src/gnuais -c ./gnuais.conf -l /root/aisfifo
Далее получаем детальный вывод фреймов, которые удалось успешно декодировать, например:
ch B type 3 mmsi 671407100: lat 25.267278 lon 55.297437 course 161 speed 0.7 rateofturn 64 navstat 1 heading 54 (!AIVDM,1,1,,A,3:0CKw50073u8Jt>MD;nBie40lLJ,0*60)
Как видно, GNU AIS автоматически преобразовал его в формат NMEA.
Безопасность
После полного изучения приема AIS можно сделать несколько выводов о его безопасности. Понятно, что протокол не подразумевает какого‑либо шифрования или подтверждения источника, а это делает его уязвимым для спуфинга и других похожих атак. Так как это очень серьезная проблема, в нулевых был разработан протокол TESLA, который позволяет шифровать сообщения, идущие друг за другом, но из‑за своей непрактичности он не нашел широкого применения. Военные же выделили себе и своим кораблям отдельный канал AIS, который уже полностью зашифрован.
Наземным станциям остается только статистический анализ передаваемых данных. Например, если судно всегда имело определенный курс, а потом данные начали показывать, что оно идет совсем в другом направлении, эти данные нужно перепроверять, так как пираты тоже могут использовать AIS и мешать работе системы.
В целом система очень старая, и накопилось приличное количество методов для анализа трафика, но даже сейчас, в мире, где есть ИИ и другие инструменты для анализа, корабли могут изменить настройки своих передатчиков и плавать совсем не там, где сообщают. Все эти атаки я разберу в следующей статье, как и передачу своего сигнала AIS.