Морські інтеграції: оцінка довіри на містку
Морська оцінка довіри Kshana (MARITIME-TRUST.md) доступна з програм, які яхтсмени вже використовують: плагін сервера Signal K та OpenCPN через gate-mode NMEA поверх TCP. Еталонна збірка розміщує її на невеликому комп'ютері поруч із приймачем.
Консультативне програмне забезпечення. Kshana не є навігаційним обладнанням із затвердженням типу (IEC 61108, IEC 61162) і не оцінювалася за жодним стандартом характеристик. Усе на цій сторінці — допомога для судження штурмана. Відповідальність за безпечну навігацію судна та за будь-яке рішення покладатися на визначення місця чи припинити покладатися на нього залишається на операторі. Ніщо тут нічого не передає, і ніщо тут не робить визначення місця точнішим.
| Елемент | Де | Стан у 0,35 |
|---|---|---|
| Плагін Signal K | integrations/signalk/ |
постачається, модульно протестовано на записаному синтетичному виході; не опубліковано в npm |
| OpenCPN через gate-mode NMEA поверх TCP | integrations/opencpn/ |
постачається й протестовано (відтворення з боку споживача); сам інтерфейс користувача OpenCPN жодним тестом не керується |
| Рідний плагін панелі оцінки для OpenCPN | integrations/opencpn/plugin/ |
створено, логіку модульно протестовано, запущено всередині OpenCPN 5.8.4 під віртуальним дисплеєм (докази в integrations/opencpn/evidence/); не запаковано для менеджера плагінів; постачатиметься лише після перегляду |
| Еталонна збірка | deploy/reference-build/ |
деталі, кроки для ОС, блоки systemd (перевірено пробним запуском), варіант із контейнером; не протестовано на судні |
Усе це читає одне: вихід kshana receiver-trust live (рядки JSON, речення $PKSHT, шлюз). Формати передавання описано в MARITIME-TRUST.md. Плагін Signal K зберігає знання про них в одному файлі, integrations/signalk/lib/adapter.js; зміна формату — це редагування одного файлу.
Плагін Signal K#
Жодних залежностей npm. Сам плагін працює на Node 18 або новішому; поточні випуски signalk-server потребують Node 22 або новішого, тож на практиці використовуйте 22. Скопіюйте або прив'яжіть integrations/signalk/ у node_modules сервера (наприклад, ~/.signalk/node_modules/signalk-kshana-trust), перезапустіть сервер і ввімкніть Kshana GNSS trust у Server, Plugin Config.
Звідки беруться епохи (source)#
source |
Що робить плагін |
|---|---|
spawn-signalk-nmea (типово) |
Запускає kshana receiver-trust live <sessionFile> і записує на його стандартний вхід кожне необроблене речення NMEA 0183, яке отримує сервер (подія nmea0183 сервера). Перезапускає його з відтермінуванням, якщо він завершується | Використовуйте лише на сервері з єдиним джерелом NMEA: він подає кожне речення від кожного постачальника впереміж, тож другий приймач ГНСС (GNSS) чи AIS виглядає як один приймач, чиє положення стрибає, і може бути оцінений як спуфінг. За кількох джерел використовуйте spawn-args із власним потоком --tcp цього приймача або tcp-pksht зі шлюзу. |
spawn-args |
Запускає kshana receiver-trust live <sessionFile> <inputArgs...>, наприклад ["--tcp","192.0.2.10:10110"] або ["--udp","10110"] |
tcp-json |
Підключається до потоку рядків JSON, які записує kshana (наприклад, з ретранслятора в integrations/opencpn/) |
tcp-pksht |
Підключається до потоку NMEA (наприклад, виходу шлюзу служби чи контейнера в еталонній збірці, порт 10110) і читає лише його речення $PKSHT |
Потік, який уже піддається спуфінгу, коли монітор уперше підключається, не має чистої базової лінії (перші calibration_s секунд ніколи не оцінюються). Запускайте його до рейсу.
Опубліковані шляхи#
Кожна епоха оновлює (джерело kshana-trust):
| Шлях | Значення |
|---|---|
navigation.gnss.kshana.band |
calibrating, nominal, degraded або untrusted |
navigation.gnss.kshana.score |
від 0 до 100 або null під час калібрування |
navigation.gnss.kshana.reasons |
[{monitor, points}], найбільші першими: які перевірки знизили оцінку |
navigation.gnss.kshana.alarms |
монітори, що наразі перевищують свій поріг |
navigation.gnss.kshana.gate |
off, passed або withheld (коли шлюз працює деінде; null від $PKSHT, коли його немає) |
navigation.gnss.kshana.reportedPosition |
{latitude, longitude, altitude}: положення, яке повідомив приймач, що перевіряється, у цю епоху (схема JSON 1,1 або новіша; не публікується, коли потік його не містить, наприклад від $PKSHT чи старішого kshana). Лише контекст довіри: плагін ніколи не записує navigation.position, тож власний шлях положення судна лишається недоторканим |
notifications.navigation.gnss.kshana.trust |
піднімається, коли стан змінюється: {state, method, message} |
Плагін також один раз на початку надсилає метадані Signal K для цих шляхів. score — це оцінка довіри Kshana від 0 до 100, оцінка, а не відношення чи ймовірність, тож вона не має одиниці SI; її метадані задають діапазон, опис і зони, що відповідають порогам нижче. reasons[].points — це бали оцінки, віднято від цієї оцінки від 0 до 100.
Сповіщення має значення normal, alert, warn або alarm. Його знімають публікацією стану normal, а не null: споживач, який вважає знятим лише null, має вважати знятим і normal. Типово смуга degraded дає warn, а смуга untrusted дає alarm, з method: ["visual","sound"]. Його знижують через clearAfterEpochs епох у кращому стані. Якщо епоха не надходить протягом staleAfterS секунд, воно попереджає, що оцінка не оновлюється. Калібрування ніколи не піднімає сповіщення. Джерело $PKSHT не містить списку alarms (речення має лише смугу, оцінку та дві головні причини).
Конфігурація (кожен поріг)#
| Ключ | Типове значення | Значення |
|---|---|---|
source |
spawn-signalk-nmea |
див. вище |
command |
kshana |
виконуваний файл (режими запуску). Він запускає будь-який виконуваний файл від імені користувача сервера: змінювати конфігурацію плагіна має змогу лише адміністратор сервера Signal K |
sessionFile |
/etc/kshana/session.toml |
межі судна, пороги та ваги оцінки (режими запуску) |
inputArgs |
[] |
аргументи, додані до kshana receiver-trust live <sessionFile> в обох режимах запуску: вхід для spawn-args, додаткові прапорці, як-от --replay (збережений журнал, поданий швидше за реальний час) для spawn-signalk-nmea. Плагін відхиляє --gate, --listen, --json і --pksht (він читає JSON від kshana зі стандартного виходу), а для spawn-signalk-nmea також прапорці входу (--stdin, --file, --tcp, --udp, --follow, --from-end) |
host, port |
127.0.0.1, 10111 |
Режими TCP (шлюз обслуговує на 10110: задайте порт для tcp-pksht) |
thresholdMode |
band |
band: смуга, яку повідомляє Kshana, з межами у файлі сесії. score: дві оцінки нижче |
warnBelowScore |
90 |
Режим score: нижче за це стан є degradedState (типова межа Kshana для nominal) |
alarmBelowScore |
55 |
Режим score: нижче за це стан є alarm (типова межа Kshana для degraded) |
degradedState |
warn |
стан для смуги degraded: normal, alert або warn |
raiseAfterEpochs |
1 |
послідовні епохи в гіршому стані, перш ніж піднімається сповіщення |
clearAfterEpochs |
10 |
послідовні епохи в кращому стані, перш ніж воно знижується |
staleAfterS |
10 |
попереджати, коли епоха не надходить так довго; 0 вимикає це |
method |
["visual","sound"] |
способи сповіщення |
Плагін не відсікає: він ніколи не змінює визначення місця. Позначення визначення місця недійсним для картографічної системи — це шлюз, нижче.
Тести#
cd integrations/signalk && npm test
node:test, без залежностей, без мережі, крім 127.0.0.1. Тести розбирають і відтворюють 66-епохний фрагмент рядків JSON і речень $PKSHT, які записав kshana receiver-trust live для синтетичної балтійської демонстрації (вигадані дані, лише текст), перевіряють збіг двох форматів, поведінку утримання та зняття, режим оцінки, застарілість і три шляхи входу щодо локального потоку та підставного дочірнього процесу. Ці тести не запускають справжній сервер Signal K; це робить окремий скриптований прогін, див. нижче.
Прогін у справжньому сервері Signal K#
integrations/signalk/evidence/ містить скрипт, що завантажує плагін у зафіксований пакет signalk-server 2.33.0 (у приватному просторі імен мережі лише для loopback) і записує те, що показують власні API REST і WebSocket сервера. Шляхи довіри з'являються, сповіщення переходить у warn, alarm, normal (після утримання) і знову warn, коли дані припиняються, а зі справжнім kshana, якому подано власний вхід NMEA сервера, він також опублікував reportedPosition, ніколи не navigation.position. Одна версія сервера, один прогін, жодного реального судна; обмеження та відтворення в README доказів.
OpenCPN#
OpenCPN читає NMEA з мережі, а kshana receiver-trust live --gate може сам обслуговувати відфільтрований потік на порту TCP.
Рекомендовано: пряме підключення.
some-nmea-source | kshana receiver-trust live session.toml --gate --listen tcp:10110
(some-nmea-source — це послідовний порт приймача, який читають за допомогою stty і cat, мультиплексор або входи --tcp/--udp самого kshana; kshana-gate.service еталонної збірки робить це під systemd.) --listen tcp:<port> прив'язується до адреси loopback; може підключатися будь-яка кількість клієнтів лише для читання, а той, що не встигає, відключається без затримки інших.
Альтернатива: ретранслятор. integrations/opencpn/nmea-tcp-relay.mjs — це розгалужувач Node без залежностей, що робить те саме для kshana без --listen або обслуговує будь-який інший потік рядків (варіант із контейнером використовує його для епох JSON):
some-nmea-source | kshana receiver-trust live session.toml --gate --json trust.jsonl \
| node integrations/opencpn/nmea-tcp-relay.mjs --listen 10110
Він пересилає байти без змін, лише цілі рядки, і відключає клієнта, який не читає. Віддавайте перевагу прямому підключенню: на один процес у ланцюжку менше.
В OpenCPN: Options, Connections, Add Connection, Network, протокол TCP, адреса 127.0.0.1, порт 10110, напрямок Input. Поки довіра не впала, потік є власним потоком приймача плюс одне речення $PKSHT на цикл. Коли вона впала, пересилане GGA має якість 0, RMC має статус V, а індикатори режиму кажуть, що визначення місця немає, із перерахованими контрольними сумами: обладнання бачить, що сам приймач оголошує визначення місця недійсним, і піднімає власну тривогу. Речення $PKSHT видно у вікні налагодження NMEA в OpenCPN (Options, Connections, «NMEA debug window»). Поля положення залишаються такими, як отримано.
Прочитайте «Gate mode» у MARITIME-TRUST.md, перш ніж на це покладатися: це опція за вибором, вона додає затримку (цикл утримується, доки його епоху не буде оцінено), є єдиною точкою в ланцюжку та може утримати добре визначення місця, так само як і пропустити підроблене.
Тести#
cd integrations/opencpn && npm test
test/relay.test.mjs відтворює записаний фрагмент синтетичного потоку з фільтрацією (186 речень навколо моменту, коли довіра падає, записано kshana receiver-trust live --gate) через ретранслятор по справжньому сокету TCP і перевіряє, що отримує споживач: потік байт у байт за довільного розбиття на частини; чинні контрольні суми для кожного речення, зокрема переписаних; GGA і RMC узгоджені, спершу чинні, потім недійсні без мерехтіння; одне $PKSHT на цикл із його полем шлюзу W точно там, де визначення місця недійсне; двоє споживачів ідентичні; частковий рядок ніколи не пересилається. Це перевіряє потік, який отримує OpenCPN, а не власний екран OpenCPN.
Наскрізна перевірка зі справжнім виконуваним файлом, не входить до типових тестів (потрібен зібраний kshana):
KSHANA_BIN=target/release/kshana npm run e2e # kshana --gate --listen | TCP consumer; the consumer's bytes must equal the gate's stdout
KSHANA_BIN=target/release/kshana npm run e2e -- relay # kshana --gate | relay | TCP consumer
Обидва запускають одногодинну синтетичну демонстрацію й перевіряють, що визначення місця стає чинним, потім недійсним, із $PKSHT на епоху.
Рідний плагін#
integrations/opencpn/plugin/ — це панель оцінки для OpenCPN (оцінка, смуга, шлюз, головні причини, сповіщення, коли довіра стає untrusted), що читає $PKSHT із власного потоку NMEA OpenCPN, тож не потребує підключення, окрім наведеного вище. Він збирається за допомогою CMake проти заголовка API плагінів OpenCPN (зафіксованого разом з комітом джерела) і wxWidgets; ctest запускає тести логіки без wx і перевіряє, що бібліотека експортує точки входу, які шукає OpenCPN. Його запускали всередині OpenCPN 5.8.4 під віртуальним дисплеєм на синтетичному потоці з фільтрацією (OpenCPN передав $PKSHT плагіну, панель стала червоною, а власне положення OpenCPN завмерло, коли шлюз увімкнувся; знімки екрана, журнал і скрипт у integrations/opencpn/evidence/), але не на справжньому робочому столі, не в інших версіях чи на інших платформах, і він не запакований для менеджера плагінів OpenCPN. Див. README.md плагіна. Він ліцензований за GPL-3.0-or-later, на відміну від решти репозиторію (LICENSING.md).
Знімки екрана з цього прогону в integrations/opencpn/evidence/ (один прогін, OpenCPN 5.8.4 під віртуальним дисплеєм, синтетичні дані; межі наведено в README.md):
Вони показують проводку та потрапляння відфільтрованого визначення місця в OpenCPN, а не те, що будь-яка тривога є своєчасною чи правильною для реального судна. Консультативне програмне забезпечення, не обладнання із затвердженням типу.
Еталонна збірка#
deploy/reference-build/: загальний перелік деталей, налаштування ОС, два блоки systemd (консультативний монітор і шлюз за вибором), варіант із контейнером і підключення Signal K. deploy/reference-build/check-units.sh запускає systemd-analyze verify на цих блоках, нічого не стартуючи.
Обмеження#
- Оцінка настільки добра, наскільки добрі перевірки за нею, які дивляться на фізику судна та його інші датчики; самоузгоджена підробка з відповідним годинником не помічається моніторами лише на NMEA (
MARITIME-TRUST.md). Відсутність тривоги не є доказом доброго визначення місця. - Жодна цифра на цій сторінці не є виміряною частотою виявлення чи хибних тривог. Тести вище перевіряють проводку на синтетичному тексті; вони нічого не кажуть про те, як будь-який монітор працює за реальних завад.
- Не є обладнанням із затвердженням типу; відповідальність залишається на операторі.