Отворен код • Python • AIS NMEA 0183

AISMixer

Платформа за обработка и маршрутизиране на AIS потоци

Нормализира · Дедуплицира · Маркира · Маршрутизира · Препраща

Приемайте AIS източници, превръщайте трафика от приемниците в един контролиран логически поток и го доставяйте до нужните именувани UDP изходи.

Обработка на AIS потоци

От трафика на приемниците до чист поток с ясни източници

AISMixer обединява транспорта, NMEA сглобяването, метаданните, дедупликацията и доставката в един път за обработка в почти реално време.

Гъвкав входящ трафик

Приема некриптиран UDP през IPv4 или IPv6, както и автентикиран и криптиран UDPSEC трафик от станции.

Извличане на AIS изречения

Извлича !AIVDM и !AIVDO от реален изход на приемници и приложения.

Multipart сглобяване

Сглобява фрагменти, пристигнали в напълно произволен ред, в завършени логически съобщения и ги извежда по реда на позициите.

Дедупликация в почти реално време

Взема едно атомарно за групата решение за всяко завършено multipart съобщение — глобално в broadcast режим или отделно за всяка цел при маршрутизиране.

Контролирани TAG метаданни

Управлява NMEA TAG s, c и g през жизнения цикъл на multipart съобщението, като държи метаданните отделени от идентичността за маршрутизиране.

Избрано препращане

Препраща приетите изречения към всеки конфигуриран UDP изход в broadcast режим или към именуваните цели, избрани от логическото маршрутизиране.

Кратък визуален преглед

Как работи AISMixer

Кратка визуална разходка от множество AIS източници през сглобяване, дедупликация, управление на TAG метаданните и логическо маршрутизиране до избрани изходи, включително nmea_sproxy и UDPSEC. Видеото е на английски.

Основа на data plane от кампании C–F, подготвена за нативна реализация

Изрична обработка, етапи с ограничен капацитет и унифициран egress

Неизменяемият ingress на ниво байтове преминава през изрично определени етапи с ограничен капацитет в рамките на един процес. След като стане наличен споделен капацитет за обработка, всеки допуснат кадър се свързва с една ProcessingSnapshot и се обработва от PythonDataPlaneProcessor, който притежава състоянието на инстанцията и остава единственият текущ продукционен и референтен процесор. Той връща един подреден неизменяем OutputBatch, чиито стойности ProcessorOutput пренасят точните байтове и числовите идентификатори на целите през egress предаването с ограничен капацитет.

UDP / UDPSEC производители Отделна ограничена опашка с IngressFrame за всеки вход
Ограничено допускане до обработка Backpressure, след което се свързва една ProcessingSnapshot
PythonDataPlaneProcessor със собствено състояние Сканиране на байтове, сглобяване, TAG политика и дедупликация
Ограничено предаване на подреден OutputBatch Точни байтове и изрични числови цели
Унифициран UDP egress Последователно локално изпращане чрез send_to_ids()

Неизменяема ingress граница

Вградените UDP и UDPSEC производители създават неизменяеми IngressFrame обекти на ниво байтове. Bytes-native сканирането и еднократно анализираните метаданни ParsedSentence пренасят информацията за фрагментите и TAG метаданните към обработката без повторно извличане.

Обвързване на snapshot след осигурен капацитет

Капацитетът за обработка се осигурява, преди една неизменяема ProcessingSnapshot да бъде свързана с кадъра. Допуснатата работа запазва тази снимка; кадрите, които още чакат за капацитет, може да видят по-късна локална за процеса подмяна на маршрутизацията.

Python процесор със собствено състояние

Една дългосрочно работеща инстанция на PythonDataPlaneProcessor притежава изменяемото състояние на сглобяването, дедупликацията, източниците, multipart метаданните и процесорните метрики. Днес не съществуват нативен процесор или bindings.

Точни байтове в подредени резултати

Всяко изведено NMEA изречение се кодира като UTF-8 веднъж и се превръща в един точен неизменяем payload в подреден OutputBatch. Всеки ProcessorOutput носи изрични числови идентификатори на целите; multipart фрагментите остават отделни payload-и.

Backpressure и подредено завършване

Когато отделна ingress граница, споделена processing граница или egress граница достигне капацитета си, изпълнението изчаква, вместо да отхвърли елемента в опашката. Непразният пакет спира обработката на следващ кадър до завършването на последователното локално изпращане. Това не осигурява трайност или потвърждение за отдалечена доставка, а UDP остава транспорт със загуби.

Локален за процеса fail-fast жизнен цикъл

Съществените asyncio етапи споделят един жизнен цикъл под fail-fast надзор в рамките на процеса. Неуспех или неочаквано завършване отменя останалите задачи и изчаква тяхното приключване; няма автоматичен рестарт, повторен опит, връщане назад, потвърждение за мрежова доставка или повторно изпращане.

Нужни са точните правила за граничните случаи? Прочетете договора за поведение.

Изрична отговорност за жизнения цикъл

Детерминирано състояние под натоварване

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

Състояние на дедупликацията

Идентичността е точното изречение или подреденият multipart кортеж в глобален обхват или в обхвата на конкретна цел. TTL е детерминиран, дубликатите не подновяват задържането, а изтеклите записи се премахват, преди да бъде премахнат най-старият активен запис.

Конструкторът на Python обекта приема незадължителен max_entries; текущото свързване в услугата го оставя със стойност None, затова този размер е неограничен в текущата услуга.

Състояние на multipart сглобяването

Фрагментите заемат поредни позиции. Уникалният напредък подновява времето на живот на групата, а точното повторение — не. Конфликтът, изтичането, премахването поради капацитет, завършването и нулирането остават отделни резултати от жизнения цикъл и почистват свързания TAG контекст.

Конструкторът на Python обекта приема незадължителни max_fragments_per_group и max_pending_groups; текущото свързване в услугата оставя и двата със стойност None.

Защита от повторения и сесии

Записите за защита от повторение при handshake, чакащите и активните сесии и частното nonce състояние, притежавано от всяка чакаща или активна сесия, са твърдо ограничени. Монотонното локално време управлява TTL, а изтеклото състояние се премахва преди детерминираното премахване на живо състояние поради капацитет.

Инсталирането на нова чакаща сесия от същия адрес заменя само по-старата чакаща сесия и запазва съществуващата активна. Активната сесия се заменя едва след автентикирано криптирано потвърждение и повишаване на чакащата сесия. Неуспешното потвърждение не я засяга; същото важи при изтичане, замяна или премахване на чакащата сесия поради капацитет. Цялото състояние е в паметта, локално за процеса и се губи при рестарт.

Наблюдаемо компонентно и runtime състояние

Собствениците на състоянието за дедупликация, сглобяване и сигурност предоставят неизменяеми вътрешни снимки на жизнения цикъл. Runtime-ът отделно предлага свежи pull-based изгледи към опашките, активността на процесора и egress етапа, както и входния и изходния трафик. Прочитането на който и да е вид снимка не променя състоянието на обработката.

Тези изгледи са локални за процеса и нетрайни; те не са разпределени метрики или система за изнасяне към Prometheus/time-series.

Локално по замисъл. Това състояние не се запазва трайно и не се споделя между процеси. Текущият runtime упражнява надзор над съществените asyncio задачи в рамките на един процес; coordinator/worker процеси, IPC и междупроцесна синхронизация на състоянието все още не съществуват.

Campaign F — реализирана

Граници, подготвени за worker архитектура в един процес

Campaign F завърши ограничените и наблюдаеми граници около текущия Python runtime. Изменяемото състояние на обработката има изричен собственик на ниво инстанция, работата се допуска само при наличен капацитет, а свежата pull-based статистика прави активността на етапите видима, без да я променя.

Отделен ограничен ingress

Всеки конфигуриран UDP или UDPSEC вход има собствена ограничена опашка, така че натрупаните елементи от един вход да не заемат отделния капацитет на друг.

Допускане само при наличен капацитет

Споделеното допускане до обработка е ограничено. Кадърът получава своята неизменяема ProcessingSnapshot едва след осигуряване на капацитет, а при достигане на капацитета изпълнението изчаква с backpressure.

Собственост на процесорната инстанция

Една процесорна инстанция притежава изменяемото състояние на сглобяването, дедупликацията, източниците, multipart метаданните и процесорните метрики зад изрична граница на жизнения цикъл.

Ограничен подреден egress

Ограничено предаване пренася всеки непразен OutputBatch към последователно локално изпращане. Бариерата за завършване запазва реда на обработка, но не е потвърждение за отдалечено получаване.

Pull-based runtime наблюдаемост

Свежите неизменяеми снимки обхващат състоянието на опашките и backpressure, активността на процесора и egress етапа, както и суровия и допуснатия входен трафик и съобщенията и байтовете за всяка цел.

Готовността за worker архитектура е реализирана; worker процесите не са. Текущата услуга все още използва един процес с наблюдавани asyncio етапи. Няма coordinator процес, отделни ingress или egress worker процеси, multiprocessing, IPC, междупроцесна маршрутизация или агрегиране на метрики, нито автоматичен рестарт и възстановяване на worker процеси. Днес няма нативен процесор или bindings.

Маршрутизиране и логически зони

Опишете политиката на потока чрез идентичности на източници

Статичното логическо маршрутизиране свързва именувани входни източници с именувани UDP изходни цели чрез многократно използваеми множества от източници и подредени маршрути. Имената остават интерфейсът за конфигурация и управление; продукционното съпоставяне използва предварително компилиран план само с числови цели.

Именуван входUDP и UDPSEC източници
Логически зониМножества от идентичности на източници
Подредени маршрутиДекларативен избор на цели
Именуван изходИзбрани UDP цели

Съставни множества от източници

Дефинирайте зони чрез include, union, intersection и difference.

Логически, не географски

Зоните са множества от вътрешни идентичности на източници, а не райони върху карта, MMSI филтри, филтри за плавателни съдове или правила по съдържанието.

Запазен ред и качество за всяка цел

Компилираният план запазва декларирания ред на целите. Режимът с маршрутизация прилага дедупликацията за всяка логическа цел поотделно, така че един път за изпращане да не потиска друг.

Имената остават операторският интерфейс. Локалните за процеса числови идентификатори на цели не са конфигурационни стойности. Идентичността source_id остава отделна от стойността на NMEA TAG s, която се изпраща надолу по потока.

Локално управление и runtime наблюдаемост

Управлявайте маршрутизацията и наблюдавайте runtime активността

Незадължителният локален управляващ слой през POSIX Unix-domain сокет предоставя операции по маршрутизиране и read-only агрегирана runtime статистика и статистика по входове и изходи чрез глобално инсталираната команда aismixerctl. Стартирането без команда отваря интерактивната операторска обвивка.

Състояние и атомарни промени на маршрутизацията

Проверявайте активното поколение, зоните, маршрутите и целите; заменете валидирана моментна снимка или изключете маршрутизацията, за да се върнете към наследения broadcast режим. Незадължителните проверки на поколението отхвърлят остарели промени.

Агрегирана runtime статистика

runtime.statistics отчита състоянието на ограничените опашки и backpressure, активността на процесора и активността на egress при едно свежо локално за процеса извличане.

Входен и изходен трафик

runtime.statistics.inputs разграничава транспортния трафик от приетите кадри. runtime.statistics.outputs отчита локалните изпращания, съобщенията и байтовете за всяка цел.

Интерактивно или с еднократна команда

Обвивката без начална команда предоставя помощ, таблици, история, когато е налична, и същите операции за маршрутизиране и статистика, запазени и за еднократно използване с JSON.

aismixerctl> status
aismixerctl> show statistics
aismixerctl> show statistics inputs
aismixerctl> show statistics outputs

Граница на read-only статистиката. Статистиката е в паметта, локална за процеса, нетрайна и се нулира при рестарт. Тя не е постоянна история, разпределени метрики или система за Prometheus/time-series. Успешното локално UDP изпращане не е потвърждение за доставка от отсрещната страна.

Умишлено локално управление. Runtime маршрутите не се запазват след рестарт, конфигурационните файлове не се пренаписват, а адаптери не се създават динамично. Правата върху Unix сокета са текущата граница за оторизация; няма управляващ token на ниво приложение.

Контрол на мрежовите крайни точки

Ограничете разрешените източници и изходните адреси

Малки механизми за контрол на ниво приложение улесняват включването на IPv4 и IPv6 крайни точки в по-широките правила на оператора за защитна стена и маршрутизиране.

Входен allow_from

Ограничете UDP и UDPSEC слушателите до конкретно зададени IP адреси или CIDR мрежи, включително с възможност за изрична пълна забрана.

Изходен source_ip

Обвържете изходящия сокет с конкретно зададен IPv4 или IPv6 адрес на източника и ограничете преобразуването на адреса на целта до същото адресно семейство.

Част от многослойна граница

Тези политики допълват правилата на операционната система за защитна стена и маршрутизиране; те не ги заменят.

source_ip задава обвързване с адрес на източника, а не избор на мрежов интерфейс, таблица за маршрутизиране, маркиране на сокет или SDN.

Жизнен цикъл на UDPSEC

Автентикиран транспорт с ограничено локално състояние

Текущият UDPSEC път през nmea_sproxy и AISMixer използва автентикиран ефемерен ECDHE обмен и независими ключове за двете посоки, с криптирано потвърждение с пореден номер нула, преди клиентът да приеме новата сесия за установена.

Автентикиран ClientHello Подпис с ключ за идентичност и нов ефемерен P-256 ключ
Ефемерен P-256 ECDHE Нова споделена тайна за този handshake
HKDF-SHA256 Независими C2S и S2C ключове
Криптирано потвърждение с пореден номер нула C2S ping, следван от S2C pong
Активна сесия Автентикираният ping повишава сесията; автентикираният pong завършва установяването

Автентикиран ефемерен обмен на ключове

При всеки handshake всяка крайна точка създава нова ефемерна ключова двойка P-256 за ECDHE. Дългосрочните P-256 ключове за идентичност служат единствено за взаимна автентикация чрез ECDSA подписи върху канонични SHA-256 хешове на транскрипта, разделени според ролята; те не участват в ECDHE договарянето на ключове.

HKDF-SHA256 извежда независими C2S и S2C ключове от споделената тайна и автентикирания транскрипт. AES-256-GCM защитава криптираните данни и управляващия трафик.

Криптирано взаимно потвърждение

Клиентът потвърждава чакащата сесия с криптиран ping по C2S с пореден номер нула. Сървърът я повишава в активна само след като удостовери ping, след което връща криптиран pong с пореден номер нула чрез S2C ключа на вече активната сесия; клиентът приема сесията за установена едва след като удостовери този pong.

Несвързани и неправилно форматирани дейтаграми, както и такива с остарял ключ, грешен пореден номер или грешен източник, нито потвърждават чакащата сесия, нито удължават фиксирания срок за потвърждение.

Съгласувано обновяване и локално състояние

Двете крайни точки трябва да бъдат обновени заедно. Няма автоматично връщане към предишния режим, смесен режим, превключвател за договаряне, система от сертификати или договаряне на алгоритми.

Разрешеният трафик задвижва почистването на изтеклите записи вместо фонов таймер. Състоянието за защита от повторения, чакащите и активните сесии и nonce стойностите е в паметта, локално за процеса, не се запазва трайно и се губи при рестарт на услугата.

Граница на защитата на миналите сесии (forward secrecy): по-късното компрометиране на дългосрочен ключ за идентичност само по себе си не възстановява ключовете на вече приключили сесии, ако старите ефемерни частни ключове и споделените ECDHE тайни вече не са налични и никоя крайна точка не е била компрометирана, докато те са били в паметта. Компрометиран в момента ключ за идентичност позволява представяне за съответната страна в бъдещи сесии. Това реализирано свойство е подкрепено от инженерна проверка, а не от формална криптографска верификация.

Граница на транспорта: UDPSEC автентикира и криптира пакетите с данни и управляващия трафик в своя обхват, но не доказва достоверността на AIS съдържанието и не открива подправяне, не гарантира доставка или ред на UDP дейтаграмите, не защитава компрометирани крайни точки и не осигурява пълна устойчивост срещу отказ на услуга. Той не скрива IP адресите на страните, моментите или размерите на пакетите, нито идентификатора на станцията, предаван като открит текст в ClientHello; NOSESSION подсказките не са автентикирани.

Прочетете политиката за сигурност, договора за поведение, ръководството за nmea_sproxy и Wiki за подробните граници.

nmea_sproxy и физически AIS приемници

Свържете мрежови или физически AIS приемници чрез nmea_sproxy

nmea_sproxy е проксито при станцията, което свързва един локален AIS източник с една конфигурирана AISMixer цел.

Физически AIS приемник
сериен порт или USB virtual COM
nmea_sproxy
UDPSEC или изрично доверен некриптиран UDP
AISMixer

Реализирани локални входове

  • UDP от локален мрежов приемник или AIS приложение.
  • Директен вход от физически сериен порт.
  • USB virtual COM вход от физически AIS приемник.

Реализирани изходи

  • Автентикиран и криптиран UDPSEC с ограничения жизнен цикъл на сесията, описан по-горе.
  • Изрично конфигуриран некриптиран UDP за доверена LAN, VPN или равностойна граница.

Ясен модел на връзката

Един локален вход се свързва с един конфигуриран изход. nmea_sproxy не смесва, не разклонява към няколко изхода, не маршрутизира, не дедуплицира, не сглобява multipart AIS и не пренаписва TAG метаданни.

Мрежов приемник може да подава локален UDP към nmea_sproxy или директно към AISMixer според внедряването. Основният AISMixer процес не чете серийни портове директно. Довереният некриптиран UDP не предоставя UDPSEC криптиране, автентикация, защита срещу повторение или проверка за активност.

Внедряване и експлоатация

Жизнен цикъл за Linux и systemd, създаден за реални инсталации

Управляваното от хранилището внедряване поддържа съгласувани файловете за изпълнение, операторското състояние, интеграцията със systemd, локалното управление на маршрутизацията и read-only runtime статистиката.

systemd услуга, управлявана от хранилището

Услугата създава /run/aismixer, докато AISMixer работи, и поддържа незадължителния локален управляващ сокет.

Инсталиране, актуализиране и деинсталиране

Скриптовете за жизнения цикъл съобразяват работата с root или sudo и поддържат внедрените файлове за изпълнение и unit файловете на услугата.

Запазени операторски настройки

Обичайните операции за инсталиране, актуализиране и деинсталиране запазват конфигурацията на оператора и криптографските ключове.

Глобален операторски CLI

Инсталацията поставя aismixerctl в /usr/local/bin за локална runtime маршрутизация и read-only статистика, включително интерактивната обвивка без начална команда.

Документация и състояние на проекта

Реализирана основа, ясно отделена от следващите стъпки

Wiki е подробното ръководство за архитектура, конфигурация, маршрутизиране, сигурност и експлоатация. Roadmap отделя завършената основа от бъдещата работа без обещани срокове.

Реализирано сега

  • Неизменяеми IngressFrame стойности на ниво байтове, bytes-native сканиране, еднократно анализирани метаданни и PythonDataPlaneProcessor като единствен текущ продукционен и референтен процесор.
  • Отделни ограничени ingress опашки, споделено ограничено допускане до обработка, ограничено egress предаване, backpressure, собственост на състоянието от процесорната инстанция и обвързване на ProcessingSnapshot при допускане.
  • Компилирана маршрутизация само към числови цели, точни неизменяеми байтове с едно кодиране за всяко изведено изречение, подредени OutputBatch резултати и подредена локална бариера за завършване на egress.
  • Логически зони и дедупликация по цели, атомарни локални за процеса промени на маршрутизацията, интерактивен aismixerctl и read-only агрегирана статистика и статистика по входове и изходи.
  • Детерминирано multipart сглобяване, управление на TAG s/c/g и глобална или отделна за всяка цел дедупликация.
  • Автентикиран ефемерен P-256 ECDHE UDPSEC, дългосрочни P-256 ECDSA идентичности, независими AES-GCM ключове за двете посоки и твърдо ограничено локално защитено състояние.
  • За всеки процес или systemd instance на nmea_sproxy — един UDP или сериен вход към един UDPSEC или изрично конфигуриран plain-UDP изход за доверена мрежа, плюс IPv4/IPv6 контрол на крайните точки.
  • systemd RuntimeDirectory, скриптове за жизнения цикъл, съобразени с наличните привилегии, запазено операторско състояние и глобален операторски CLI.

Планирана работа

  • Координаторен процес и реални отделни ingress и egress worker процеси.
  • IPC, междупроцесно разпространение на routing snapshot-и и надзор, политика за рестарт и възстановяване на worker процесите и при нужда агрегиране на метрики.
  • Бъдещ нативен процесор и bindings зад установените договори с диференциална проверка за съответствие; днес такава реализация няма и не се твърдят резултати за производителност.
  • По-широка архитектура за входни и изходни адаптери отвъд текущите UDP пътища.

Общност на проекта

Общност и контакт

Изберете публичния канал според вида на разговора. Discussions, Ideas и Q&A помагат и на други потребители, а възпроизводимите дефекти се докладват в Issues. Личният контакт остава достъпен в профила на отговорника за поддръжката по-долу.

Разгледайте дискусиите

Разгледайте публичните разговори за проекта, съобщенията, опита от внедряване, полевите тестове и другите теми на общността.

Разгледайте GitHub Discussions

Споделете идея

GitHub Discussions е подходящо място за архитектурни предложения, идеи за интеграция, опит от внедряване, полеви AIS тестове и академично или изследователско сътрудничество, което може да се обсъжда публично.

Отворете Ideas

Докладвайте проблем

Използвайте GitHub Issues за възпроизводими дефекти и конкретна работа по хранилището, а не за обща лична кореспонденция.

Отворете GitHub Issues

Задайте въпрос в Q&A

Използвайте Q&A за конкретни въпроси относно инсталирането, конфигурацията, използването, архитектурата и експлоатацията.

Отворете Q&A

Основател и отговорник за поддръжката

Iliyan Iliev, PhD

Основател, идеолог и отговорник за поддръжката на AISMixer

Разработчик и изследовател в областта на сървърните и мрежовите системи с интереси в обработката на AIS/NMEA данни, морската и регионалната сигурност, транспорта и туризма.

Разработка с ИИ съдействие: ChatGPT подпомага архитектурното обмисляне, планирането, документацията и прегледите. OpenAI Codex подпомага анализа на хранилището, реализацията, тестовете и проверките. И двата инструмента се използват под ръководството на основателя; решенията и крайната отговорност за проекта остават човешки.