Tradução automática, não revista por um falante nativo. O inglês é a referência.

Confiança do recetor e marítimoEditar no GitHubFonte: docs/MARINE-INTEGRATIONS.md

Integrações marítimas: a pontuação de confiança na ponte

A pontuação de confiança marítima do Kshana (MARITIME-TRUST.md) é acessível a partir de software que os navegadores de recreio já usam: um plugin de servidor Signal K e o OpenCPN através de NMEA em modo gate sobre TCP. Uma compilação de referência coloca-a num computador pequeno junto do recetor.

Software de caráter consultivo. O Kshana não é um equipamento de navegação homologado (IEC 61108, IEC 61162) e não foi avaliado face a nenhuma norma de desempenho. Tudo nesta página é um auxiliar do juízo do navegador. O operador continua a ser responsável pela navegação segura da embarcação e por qualquer decisão de confiar, ou de deixar de confiar, numa solução de posição. Nada aqui transmite, e nada aqui torna uma solução de posição mais exata.

Componente Onde Estado em 0,35
Extensão para o Signal K integrations/signalk/ entregue, com testes unitários sobre saída sintética registada; não publicado no npm
OpenCPN através de NMEA em modo gate sobre TCP integrations/opencpn/ entregue e testado (repetição do lado do consumidor); a própria interface de utilizador do OpenCPN não é acionada por nenhum teste
Plugin nativo de painel de pontuação para o OpenCPN integrations/opencpn/plugin/ construído, com a lógica testada unitariamente, e executado dentro do OpenCPN 5.8.4 sob um ecrã virtual (evidências em integrations/opencpn/evidence/); não empacotado para o gestor de plugins; só é entregue após revisão
Compilação de referência deploy/reference-build/ peças, passos do sistema operativo, unidades systemd (verificadas em simulação), uma opção de contentor; não testada numa embarcação

Tudo isto lê uma só coisa: a saída de kshana receiver-trust live (linhas JSON, a sentença $PKSHT, o gate). Os formatos de transmissão constam de MARITIME-TRUST.md. O plugin Signal K guarda o seu conhecimento deles num só ficheiro, integrations/signalk/lib/adapter.js; uma alteração de formato é uma edição de um só ficheiro.

Extensão para o Signal K#

Sem dependências npm. O próprio plugin corre em Node 18 ou posterior; as versões atuais de signalk-server exigem Node 22 ou posterior, pelo que, na prática, se usa 22. Copie ou ligue integrations/signalk/ para a pasta node_modules do servidor (por exemplo ~/.signalk/node_modules/signalk-kshana-trust), reinicie o servidor e ative Kshana GNSS trust em Server, Plugin Config.

De onde vêm as épocas (source)#

source O que o plugin faz
spawn-signalk-nmea (predefinição) Executa kshana receiver-trust live <sessionFile> e escreve na sua entrada padrão cada sentença NMEA 0183 em bruto que o servidor recebe (o evento nmea0183 do servidor). Reinicia-o, com recuo progressivo, se terminar | Use-o apenas num servidor com uma única fonte NMEA: alimenta todas as sentenças de todos os fornecedores, intercaladas, pelo que um segundo recetor GNSS ou o AIS parece um só recetor cuja posição salta e pode ser pontuado como spoofing. Com mais de uma fonte, use spawn-args com o fluxo --tcp do próprio recetor, ou tcp-pksht a partir de um gate.
spawn-args Executa kshana receiver-trust live <sessionFile> <inputArgs...>, por exemplo ["--tcp","192.0.2.10:10110"] ou ["--udp","10110"]
tcp-json Liga-se a uma alimentação das linhas JSON que kshana escreve (por exemplo, a partir do retransmissor em integrations/opencpn/)
tcp-pksht Liga-se a um fluxo NMEA (como a saída do gate do serviço ou do contentor na compilação de referência, porta 10110) e lê apenas as suas sentenças $PKSHT

Um fluxo que já esteja a ser alvo de spoofing quando o monitor se liga pela primeira vez não tem linha de base limpa (os primeiros calibration_s segundos nunca são pontuados). Inicie-o antes da viagem.

Caminhos publicados#

Cada época atualiza (fonte kshana-trust):

Caminho Valor
navigation.gnss.kshana.band calibrating, nominal, degraded ou untrusted
navigation.gnss.kshana.score 0 a 100, ou null durante a calibração
navigation.gnss.kshana.reasons [{monitor, points}], do maior para o menor: que verificações reduziram a pontuação
navigation.gnss.kshana.alarms os monitores que estão neste momento acima do seu limiar
navigation.gnss.kshana.gate off, passed ou withheld (quando um gate está em execução noutro local; null a partir de $PKSHT quando ausente)
navigation.gnss.kshana.reportedPosition {latitude, longitude, altitude}: a posição que o recetor em teste indicou nessa época (esquema JSON 1,1 ou posterior; não publicada quando o fluxo não a traz, por exemplo a partir de $PKSHT ou de um kshana mais antigo). Apenas contexto de confiança: o plugin nunca escreve navigation.position, pelo que o caminho de posição da própria embarcação não é tocado
notifications.navigation.gnss.kshana.trust emitida quando o estado muda: {state, method, message}

O plugin envia também, uma vez no arranque, metadados Signal K para estes caminhos. score é a pontuação de confiança de 0 a 100 do Kshana, uma pontuação e não uma razão nem uma probabilidade, pelo que não tem unidade SI; os seus metadados dão o intervalo, uma descrição e zonas que seguem os limiares abaixo. reasons[].points são pontos de pontuação retirados a essa pontuação de 0 a 100.

A notificação é normal, alert, warn ou alarm. É limpa publicando o estado normal, não null: um consumidor que só trate null como limpo deve tratar normal também como limpo. Por predefinição, a faixa degraded dá warn e a faixa untrusted dá alarm, com method: ["visual","sound"]. É reduzida após clearAfterEpochs épocas num estado melhor. Se não chegar nenhuma época durante staleAfterS segundos, avisa que a pontuação não está a ser atualizada. A calibração nunca gera uma notificação. A fonte $PKSHT não traz lista alarms (a sentença tem apenas a faixa, a pontuação e os dois principais motivos).

Configuração (todos os limiares)#

Chave Predefinição Significado
source spawn-signalk-nmea ver acima
command kshana o executável (modos spawn). Executa qualquer executável como utilizador do servidor: só um administrador do servidor Signal K deve poder alterar a configuração do plugin
sessionFile /etc/kshana/session.toml os limites, limiares e pesos de pontuação da embarcação (modos spawn)
inputArgs [] argumentos acrescentados a kshana receiver-trust live <sessionFile> nos dois modos spawn: a entrada para spawn-args, sinalizadores adicionais como --replay (um registo guardado alimentado mais depressa do que em tempo real) para spawn-signalk-nmea. O plugin recusa --gate, --listen, --json e --pksht (lê o JSON de kshana na saída padrão) e, para spawn-signalk-nmea, também os sinalizadores de entrada (--stdin, --file, --tcp, --udp, --follow, --from-end)
host, port 127.0.0.1, 10111 Modos TCP (o gate serve em 10110: defina a porta para tcp-pksht)
thresholdMode band band: a faixa que o Kshana indica, com os limites no ficheiro de sessão. score: as duas pontuações abaixo
warnBelowScore 90 modo score: abaixo deste valor o estado é degradedState (limite predefinido do Kshana para nominal)
alarmBelowScore 55 modo score: abaixo deste valor o estado é alarm (limite predefinido do Kshana para degraded)
degradedState warn estado para a faixa degraded: normal, alert ou warn
raiseAfterEpochs 1 épocas consecutivas num estado pior antes de a notificação ser emitida
clearAfterEpochs 10 épocas consecutivas num estado melhor antes de ser reduzida
staleAfterS 10 avisar quando não chega nenhuma época durante este tempo; 0 desativa-o
method ["visual","sound"] métodos de notificação

O plugin não faz de gate: nunca altera uma solução de posição. Marcar uma solução de posição como inválida para um sistema de cartas é o gate, abaixo.

Testes#

cd integrations/signalk && npm test

node:test, sem dependências, sem rede para além de 127.0.0.1. Os testes interpretam e repetem um excerto de 66 épocas das linhas JSON e das sentenças $PKSHT que kshana receiver-trust live escreveu para a demonstração sintética do Báltico (dados fictícios, só texto), verificam a concordância entre os dois formatos, o comportamento de retenção e de limpeza, o modo de pontuação, a obsolescência e os três caminhos de entrada face a uma alimentação local e a um processo-filho de substituição. Esses testes não iniciam um servidor Signal K real; uma execução separada com script fá-lo, ver abaixo.

Execução num servidor Signal K real#

integrations/signalk/evidence/ contém um script que carrega o plugin no pacote signalk-server 2.33.0 fixado (num espaço de nomes de rede privado, só de loopback) e regista o que as próprias APIs REST e WebSocket do servidor mostram. Os caminhos de confiança aparecem, a notificação passa por warn, alarm, normal (após a retenção) e warn de novo quando os dados cessam, e com o kshana real alimentado pela própria entrada NMEA do servidor publicou também reportedPosition, nunca navigation.position. Uma versão do servidor, uma execução, nenhuma embarcação real; limites e reprodução no README das evidências.

OpenCPN#

O OpenCPN lê NMEA a partir da rede, e kshana receiver-trust live --gate pode servir o fluxo filtrado por gate numa porta TCP por si próprio.

Recomendado: a ligação direta.

some-nmea-source | kshana receiver-trust live session.toml --gate --listen tcp:10110

(some-nmea-source é a porta série do recetor lida com stty e cat, um multiplexador, ou as entradas --tcp/--udp do próprio kshana; o kshana-gate.service da compilação de referência faz isto sob o systemd.) --listen tcp:<port> liga-se ao endereço de loopback; qualquer número de clientes só de leitura se pode ligar, e aquele que não consiga acompanhar é descartado sem atrasar os outros.

Alternativa: o retransmissor. integrations/opencpn/nmea-tcp-relay.mjs é um distribuidor Node sem dependências que faz o mesmo para um kshana sem --listen, ou serve qualquer outro fluxo de linhas (a opção de contentor usa-o para as épocas JSON):

some-nmea-source | kshana receiver-trust live session.toml --gate --json trust.jsonl \
  | node integrations/opencpn/nmea-tcp-relay.mjs --listen 10110

Encaminha os bytes sem alterações, apenas linhas inteiras, e descarta um cliente que não leia. Prefira a ligação direta: menos um processo na cadeia.

No OpenCPN: Options, Connections, Add Connection, Network, protocolo TCP, endereço 127.0.0.1, porta 10110, direção Input. Enquanto a confiança não está colapsada, o fluxo é o do próprio recetor, mais uma sentença $PKSHT por ciclo. Enquanto está colapsada, a GGA encaminhada tem qualidade 0, a RMC tem estado V e os indicadores de modo dizem sem posição, com os checksums recalculados: o equipamento vê o próprio recetor declarar a solução de posição inválida e emite o seu próprio alarme. As sentenças $PKSHT são visíveis na janela de depuração NMEA do OpenCPN (Options, Connections, "NMEA debug window"). Os campos de posição ficam como foram recebidos.

Leia "Gate mode" em MARITIME-TRUST.md antes de confiar nisto: é facultativo, acrescenta latência (um ciclo fica retido até a sua época ser pontuada), é um ponto único na cadeia e pode reter uma boa solução de posição, além de deixar passar uma falsificada.

Testes#

cd integrations/opencpn && npm test

test/relay.test.mjs repete um excerto registado do fluxo sintético filtrado por gate (186 sentenças em torno do momento em que a confiança colapsa, escritas por kshana receiver-trust live --gate) através do retransmissor sobre um socket TCP real e verifica o que um consumidor recebe: o fluxo byte a byte sob fragmentação arbitrária; checksums válidos em todas as sentenças, incluindo as reescritas; GGA e RMC concordantes, válidas e depois inválidas sem oscilação; uma $PKSHT por ciclo com o seu campo de gate W exatamente onde a solução de posição é inválida; dois consumidores idênticos; uma linha parcial nunca encaminhada. Isto verifica o fluxo que é entregue ao OpenCPN, não o ecrã do próprio OpenCPN.

Uma verificação de ponta a ponta com o binário real, que não faz parte dos testes predefinidos (precisa de um kshana compilado):

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

Ambos executam a demonstração sintética de uma hora e verificam que a solução de posição passa a válida e depois a inválida, com uma $PKSHT por época.

Plugin nativo#

integrations/opencpn/plugin/ é um painel de pontuação para o OpenCPN (pontuação, faixa, gate, principais motivos, um alerta quando a confiança passa a untrusted) que lê $PKSHT do próprio fluxo NMEA do OpenCPN, pelo que não precisa de nenhuma ligação para além da acima. É compilado com CMake contra o cabeçalho da API de plugins do OpenCPN (incluído, com o seu commit de origem) e o wxWidgets; ctest executa os testes de lógica sem wx e verifica que a biblioteca exporta os pontos de entrada que o OpenCPN procura. Foi executado dentro do OpenCPN 5.8.4 sob um ecrã virtual no fluxo sintético filtrado por gate (o OpenCPN entregou $PKSHT ao plugin, o painel ficou vermelho e a própria posição do OpenCPN congelou quando o gate entrou em ação; capturas de ecrã, registo e script em integrations/opencpn/evidence/), mas não num ambiente de trabalho real, noutras versões ou plataformas, e não está empacotado para o gestor de plugins do OpenCPN. Ver o README.md do plugin. Está licenciado sob GPL-3.0-or-later, ao contrário do resto do repositório (LICENSING.md).

Capturas de ecrã dessa execução, em integrations/opencpn/evidence/ (uma execução, OpenCPN 5.8.4 sob um ecrã virtual, dados sintéticos; README.md indica os limites):

A janela de cartas do OpenCPN a executar o plugin de painel de pontuação do Kshana no fluxo sintético filtrado por gate, antes do colapso da confiança: nenhum painel está aberto (abre-se sozinho com o alarme), a posição do navio na barra de estado indica 54 32,4659 N 018 46,1670 E com velocidade 16,48 kn e rumo 088, e o indicador de posição no canto superior direito mostra três barras. A mesma janela do OpenCPN após o colapso: o painel do Kshana está aberto a vermelho com a pontuação 47 e a palavra UNTRUSTED, as linhas gate: fix marked invalid, cn0-spread -30.0, speed-log -21.0 e idade 2 s, e a declaração de que se trata de software de caráter consultivo, não de um equipamento de navegação homologado, e de que o operador continua a ser responsável. A barra de estado continua a indicar 54 32,4672 N 018 46,2227 E, e o indicador de posição desceu para duas barras. O OpenCPN alimentado diretamente por kshana receiver-trust live --gate --listen: o painel do Kshana está aberto a vermelho com a pontuação 44 e UNTRUSTED, as linhas gate: fix marked invalid, cn0-spread -30.0, speed-log -18.8 e idade 1 s, e a declaração consultiva. Esta execução não sustenta a observação do congelamento da posição: o OpenCPN ainda estava a processar a rajada inicial de épocas.

Estas mostram a canalização e a solução de posição filtrada por gate a chegar ao OpenCPN, não que algum alarme seja atempado ou correto para uma embarcação real. Software de caráter consultivo, não um equipamento homologado.

Compilação de referência#

deploy/reference-build/: uma lista genérica de peças, a configuração do sistema operativo, duas unidades systemd (o monitor consultivo e o gate facultativo), uma opção de contentor e a ligação ao Signal K. deploy/reference-build/check-units.sh executa systemd-analyze verify nas unidades sem iniciar nada.

Limites#

  • A pontuação vale apenas o que valem as verificações que a sustentam, que observam a física do navio e os seus outros sensores; uma falsificação autoconsistente com um relógio coincidente não é vista por monitores apenas NMEA (MARITIME-TRUST.md). A ausência de alarme não é evidência de uma boa solução de posição.
  • Nenhum valor nesta página é uma taxa de deteção ou de falso alarme medida. Os testes acima verificam a canalização em texto sintético; nada dizem sobre o desempenho de qualquer monitor perante interferência real.
  • Não homologado; o operador continua a ser responsável.