Confiança marítima: a ponte de comando pode confiar nesta posição?
kshana receiver-trust pode calcular, para uma embarcação em movimento, uma pontuação de confiança de 0 a 100 em tempo real para cada posição, a partir do que qualquer receptor já coloca no barramento (primeiro NMEA 0183), e dizer quais verificações a reduziram. É uma camada de software que fica ao lado de um receptor. Não é um receptor, não substitui um e não torna uma posição mais precisa.
Software de caráter consultivo. O Kshana não é um equipamento de navegação homologado (IEC 61108, IEC 61162) e não foi avaliado em relação a nenhuma norma de desempenho. Sua pontuação e seu gate são auxílios ao julgamento do navegador. O operador continua responsável pela navegação segura da embarcação e por qualquer decisão de confiar, ou de deixar de confiar, em uma posição.
Esta página diz o que as verificações examinam, o que cada uma pode e não pode detectar, como executá-lo em tempo real e o que o gate faz. O mapeamento da pontuação e todos os valores padrão estão em RECEIVER-TRUST.md.
O que ele lê#
Uma embarcação é declarada no arquivo de sessão, com seus limites enunciados antes da execução:
[platform]
kind = "vessel"
max_speed_kn = 20.0 # includes any current you want to allow for: it limits speed over ground
max_accel_mps2 = 0.2
max_turn_rate_dps = 2.0
antenna_height_m = 18.0 # antenna above the waterline
heading_sensor = true # the stream carries a gyro or compass heading
| Sentença | Lido |
|---|---|
| GGA | posição, qualidade da posição (0 = sem posição), altitude acima do nível médio do mar, separação do geoide, HDOP |
| RMC | status (A válido, V não), velocidade e rumo sobre o solo, data, modo |
| VTG | velocidade e rumo sobre o solo, quando o RMC não traz |
| HDT, THS | proa (THS apenas quando seu modo não é V) |
| VHW, VBW | velocidade na água (VBW apenas quando seu status é A) |
| ZDA | hora |
| GSV | intensidade do sinal por satélite (dB-Hz), elevação e azimute (para a geometria) |
| GSA | diluição de precisão e satélites usados (para a geometria, onde o GSV não dá céu; e o HDOP declarado que a salvaguarda compara) |
$PKSOS,<A/F/N> |
um status OSNMA informado por um receptor, traduzido para esta sentença pelo adaptador que lê o receptor: A autenticado, F falhou, N sem resultado |
Épocas que o próprio receptor diz não serem uma posição por satélite (qualidade GGA 0, ou de 6 a 8: estimada, manual, simulador; status RMC V, ou modo E, M, S, N) não são usadas nas verificações de posição e não carregam evidência em nenhum sentido: o receptor já o disse.
Os primeiros calibration_s segundos formam a linha de base e nunca são pontuados. Cada monitor olha apenas para a época atual e as anteriores, de modo que uma decisão em uma época não muda quando chegam dados posteriores, e um fluxo ao vivo dá a mesma pontuação que o mesmo texto lido como arquivo.
O que cada verificação detecta, e o que ela não consegue detectar#
As direções entre posições (o rumo da derrota usado pela verificação da taxa de giro, o rumo implicado por duas posições) são a direção da corda entre elas, que é o azimute médio da geodésica entre as posições, não o azimute direto na primeira posição; os dois diferem em cerca de metade da convergência dos meridianos entre as posições (0,001 grau para uma linha de base de 260 m a 59,5 graus de latitude).
Uma posição falsificada precisa concordar com a física de um navio e com os outros sensores do navio. Cada verificação compara a posição com um deles. Uma verificação é tão independente quanto sua outra fonte: uma proa de uma bússola GNSS, ou uma "velocidade na água" derivada do GNSS, não é independente do receptor sob teste e não acrescenta nada.
| Verificação | Detecta | Não consegue |
|---|---|---|
kinematic |
um salto de posição; uma trajetória cujo movimento a velocidade e o rumo informados não explicam; uma velocidade, aceleração ou taxa de giro implícitas acima dos limites declarados da embarcação | um arrasto cuja velocidade e cujo rumo informados seguem a trajetória falsa e permanece dentro dos limites (o receptor os deriva de sua própria solução, de modo que concordam entre si); um limite de velocidade declarado alto demais |
heading-course |
uma trajetória que se afasta de onde o navio aponta em mais que o ângulo de deriva declarado | um arrasto ao longo do rumo (o rumo não muda); um aproamento do mesmo receptor ou de uma bússola GNSS; uma deriva transversal acima da tolerância (alarme falso); velocidades abaixo de min_speed_kn |
speed-log |
um arrasto que altera a velocidade sobre o fundo em relação à velocidade através da água | um registro derivado de GNSS; uma corrente acima da margem (alarme falso); um arrasto mais lento que a margem |
sea-level |
uma altitude que não está onde a superfície do mar e a altura de antena declarada a colocariam | um falsificador que mantém a altitude plausível; a tolerância é larga porque o erro vertical isolado é grande; a separação do geoide é registrada, mas não verificada, porque o motor não tem modelo de geoide |
cn0-spread, cn0-rise |
a assinatura de um único transmissor: C/N0 entre os satélites caindo em conjunto, ou subindo em conjunto, em relação à linha de base de calibração | um falsificador que molda a potência por satélite; qualquer coisa enquanto a própria linha de base está falsificada; uma cadência de GSV lenta demais para acompanhar |
time-consistency |
o tempo do receptor avançando de forma irregular ou retrocedendo; em relação ao relógio deste computador, o tempo do receptor se afastando dele (somente fluxos em tempo real) | um tempo falso consistente e estável; um relógio errado desde o início |
osnma |
uma falha de autenticação OSNMA informada | o estado é lido, não verificado; um falsificador que suprime o relatório não é visto |
cn0-drop, loss-of-lock, agc, jam-ind |
negação de potência e perda de satélites, como no caso estático | indicam que o ambiente é hostil, não que a posição esteja errada |
O que monitores apenas NMEA não conseguem fazer. Um falsificador que reproduz toda a constelação com uma posição autoconsistente, velocidade, rumo compatível com o aproamento, potência plausível por satélite e um relógio coincidente é invisível a todas as verificações acima: nada nas sentenças distingue sua posição de uma real. Tampouco uma repetição de sinais reais gravados. Autenticação (OSNMA, ou um receptor com recursos próprios de antifalsificação) e sensores de navegação independentes são o que fecha essa lacuna; esta camada só pode usar o estado que eles informam. Um fluxo que já está sendo falsificado enquanto a linha de base se forma não tem linha de base limpa. A ausência de um alarme não é evidência de uma boa posição.
Pontuação de confiança#
Cada época após a calibração recebe uma pontuação de 0 a 100 e os motivos de ela não ser 100: quais verificações descontaram, sua estatística contra o limiar e seus pontos. Faixas (limites declarados na sessão): nominal em 90 ou mais, degraded em 55 ou mais, untrusted abaixo disso. O mapeamento, cada peso e seu motivo estão em RECEIVER-TRUST.md; é determinístico e fixado antes de um registro ser pontuado, sem aprendizado e sem nada ajustado a eventos.
Toda saída de embarcação traz o aviso consultivo: a chave advisory do JSON de resultado e de cada linha ao vivo, uma primeira linha de comentário # do CSV (os leitores a pulam com sua opção de comentário), o <desc> e um rodapé do SVG. Saídas de uma execução em lote: session.result.json (com o modelo de pontuação e os descontos de cada época), session.trust.csv (com colunas score e score_reasons) e session.trust.svg, que para uma embarcação é a trajetória informada pelo receptor colorida pela faixa de confiança acima da pontuação ao longo do tempo.
Uma demonstração sintética#
examples/maritime-trust/ contém um registro NMEA fictício de uma balsa em uma rota de Tallinn a Helsinque (um trecho de 50 minutos, cerca de 17 nós, 1 Hz: GGA, RMC, VTG, um aproamento de giroscópio, um log de velocidade, GSV com um céu plausível) no qual um arrasto de posição afasta a posição informada da posição real da embarcação a partir de 1500 s. O receptor continua informando uma posição válida o tempo todo; é a pontuação de confiança que cai, passando pela faixa degradada até a não confiável. session.toml declara todo limiar, os limites da embarcação e todo peso de pontuação antes da execução.
kshana receiver-trust examples/maritime-trust/session.toml
kshana receiver-trust live examples/maritime-trust/session.toml \
--file examples/maritime-trust/tallinn-helsinki.nmea --gate --json trust.jsonl > gated.nmea
O registro é texto gravado em um arquivo por cargo run --example gen_maritime_trust_demo: não modela nenhum sinal de rádio e não transmite nada. Não é uma medição e a rota é ilustrativa, não uma carta náutica. tests/receiver_trust_maritime_demo.rs fixa o registro e a saída esperada como guardas de regressão sobre os dados sintéticos; eles nada dizem sobre o desempenho de qualquer monitor diante de interferência real.
A figura é desenhada por tools/gen_readme_assets.py a partir de uma execução real desta demonstração (kshana receiver-trust examples/maritime-trust/session.toml); a pontuação é consultiva e o registro é fictício.
Especificação da vista do Studio#
Para quem constrói a vista do Studio de uma execução de embarcação. Nada nesta seção está implementado ainda no Studio; o lado do motor (os dados abaixo) está.
Entradas. Qualquer uma destas:
- o JSON de resultado de uma execução em lote (
kshana receiver-trust <session.toml>, ou o mesmo porreceiver_trust(toml)no pacote WebAssembly com o registro em linha):score_model(limites de faixa, rampa, retenção de evidência, todo peso),monitors_run,stateseepochs[], cada um comt_s,state,alarms,score.{score,band,deductions[]},marine.{position:[lat,lon], stats, ratios}e, a partir da 0,36,geometrye aclassde cada desconto, comgeometry_modelegeometry_summaryno nível superior; ou - as linhas JSON ao vivo (esquema acima), um objeto por época, acrescentadas à medida que o fluxo corre. Cada linha traz a
positioninformada pelo receptor (esquema 1,1).
O conjunto de demonstração é examples/maritime-trust/: session.toml, tallinn-helsinki.nmea (o registro) e tallinn-helsinki.truth.csv (t_s,true_lat_deg,true_lon_deg: onde a embarcação realmente esteve, o que nenhum registro real tem). Uma vista deve executar a sessão e ler o arquivo de verdade ao lado.
O que desenhar.
- Trajetória, norte para cima, uma escala nos dois eixos: as posições informadas pelo receptor como uma linha colorida pela faixa da época (cinza em calibração, verde nominal, âmbar degradado, vermelho não confiável), início e fim marcados, uma barra de escala. Para a demonstração, a trajetória verdadeira como uma linha fina neutra por baixo, de modo que o arrasto apareça como as duas se separando; uma chave para a trajetória verdadeira e uma leitura do afastamento em metros no instante do cursor.
- Linha do tempo da pontuação: a pontuação de 0 a 100 contra o tempo, os limites das faixas (
nominal_min,degraded_mindescore_model) como linhas tracejadas, a faixa como uma tira por baixo e o início de qualquer evento declarado como um marcador. O eixo do tempo é compartilhado com a trajetória. - Motivos: para a época sob o cursor, os descontos (monitor, razão contra o limiar, pontos) como barras horizontais, o maior primeiro, com o peso que cada monitor carrega de
score_model.weights; monitores que rodaram e nada custaram mostrados esmaecidos, monitores que não rodaram (fora demonitors_run) listados como "não executado", nunca como tendo passado. O monitorgeometrynão tem entrada emscore_model.weights: seu teto égeometry_model.cap_in_force. - Tiras de monitores: uma tira fina por monitor em
monitors_runmostrando sua razão ao longo do tempo (alarme em 1), de modo que o leitor veja qual verificação se moveu primeiro. - Estado do portão: em uma vista ao vivo, o
gatede cada época (off,passed,withheld) como uma tira sob a tira de faixa, e o$PKSHTmais recente. Em uma vista em lote, as épocas que um portão teria retido são aquelas cuja faixa é não confiável, com a retenção de liberação aplicada. - Faixa de geometria (0,36): uma tira sob a tira de faixa colorida por
geometry.status(verde boa, âmbar degradada, cinza hachurada desconhecida), em uma família de cores distinta das faixas de inconsistência e de ambiente, com a legenda "geometria: o céu, não o sinal". Descontos coloridos porclass(geometria, ambiente, inconsistência) no painel de motivos e nas tiras de monitores, e as contagens de épocas por classe degeometry_summaryao lado das contagens por faixa. Para a época sob o cursor:geometry.note,n_used, HDOP, PDOP, VDOP,source,age_se um sinalizador quandoreported_derived_mismatchestá definido (o desconto de geometria é então uma inconsistência).unknowné mostrado como "geometria desconhecida: sem GSV nem GSA no registro", nunca como boa. Os limiares de[geometry]e sua proveniência degeometry_modelficam ao lado dos ajustes da pontuação. A nota consultiva permanece. - Posição informada pelo receptor: o receptor da demonstração informa uma posição válida o tempo todo (qualidade GGA 1, estado RMC A); diga isso na legenda, porque esse é o ponto da vista.
Interações. Um cursor de tempo compartilhado por todos os painéis (arrastar, teclas de seta e um botão de reprodução que repete de 1x a 60x); passar o mouse sobre a trajetória ou sobre qualquer tira o move. Clicar em um desconto destaca as épocas em que aquele monitor esteve acima de seu início. Um filtro de faixa (mostrar apenas épocas degradadas e não confiáveis) e um salto para o primeiro desconto e para a primeira época não confiável. Texto de passagem do mouse em cada nome de monitor dando a descrição de uma linha desta página. Os limiares e pesos da sessão são mostrados, somente leitura, ao lado do gráfico, de modo que o que a pontuação usou fique na tela.
Redação a manter. A página deve dizer que é um software de caráter consultivo e não um equipamento de navegação homologado, que a demonstração é texto sintético com um arrasto fictício e que uma posição sem alarme não é por isso uma boa posição (veja os limites acima). Nenhum valor na página deve ser lido como medida do desempenho das verificações diante de interferência real.
A partir do código#
Para chamadores que mantêm a sessão e os bytes em memória (sem arquivos, sem relógio, sem sockets; seguro para WebAssembly), kshana::receiver_trust::assess tem:
assess_vessel_log(session_toml, log_bytes) -> Result<ReceiverTrustResult, String>: um registro inteiro, pontuado como uma execução em lote; o mesmo resultado dekshana receiver-trust <session.toml>, que se serializa no JSON de resultado (score_model,monitors_run,epochs[]com pontuações e descontos).assess_stream_excerpt(session_toml, excerpt_bytes) -> Result<ExcerptAssessment, String>: um trecho limitado de um fluxo (no máximo 2 MiB e 20.000 épocas, e longo o bastante para conter a janela de calibração), pontuado como o modo ao vivo pontua e devolvido no esquema de linhas JSON ao vivo (epochs[], o último$PKSHT, um resumo das contagens por faixa, pontuação mais baixa e final, primeiro instante não confiável). O tempo do receptor não é comparado com um relógio do hospedeiro. O modo ao vivo de longa duração (sockets, um arquivo sendo acrescentado, o portão) é do binário.
Ambos precisam de uma sessão com [platform] kind = "vessel"; sua tabela [log] é opcional.
Execute ao vivo#
# stdin: a serial port read by another tool, or a multiplexer's output
some-nmea-source | kshana receiver-trust live session.toml
# a log file that is being appended to (it starts at the beginning; --from-end skips what is there)
kshana receiver-trust live session.toml --file /var/log/nmea.log --follow
# a TCP server (a multiplexer or a terminal server) or UDP datagrams (a bridge network)
kshana receiver-trust live session.toml --tcp 192.0.2.10:10110
kshana receiver-trust live session.toml --udp 10110
A sessão é o mesmo session.toml de uma execução em lote, com uma tabela [platform] que declara kind = "vessel"; sua tabela [log] não é necessária. As portas seriais ainda não são abertas diretamente: leia a porta com a ferramenta que você já usa (stty e cat, um servidor de terminal, um multiplexador) e redirecione ou encaminhe. A entrada serial direta pode vir depois.
Cada época concluída grava uma linha JSON na saída padrão:
{"seq":941,"t_s":940.0,"time":"2025-06-14T08:15:40.000Z","state":"degraded","score":60.0,
"deductions":[{"monitor":"heading-course","ratio":1.5,"points":40.0}],
"alarms":["heading-course"],"gate":"off","note":null,
"position":{"lat_deg":59.8123456,"lon_deg":24.9012345,"height_m":39.4}}
state é calibrating, nominal, degraded ou untrusted (a faixa da pontuação, com os limites na tabela [score] da sessão); score está ausente durante a calibração; deductions lista quais verificações tiraram pontos e quantos, o maior primeiro.
Esquema de linhas JSON (versão 1,1)#
Um objeto JSON por época concluída, chaves nesta ordem:
| Chave | Tipo | Significado |
|---|---|---|
seq |
inteiro | contagem de épocas informadas, a partir de 1 |
t_s |
número | segundos desde a primeira época do fluxo |
time |
string ou nulo | o tempo da época como o fluxo o declara (ISO-8601 UTC com data depois que um RMC foi visto, senão hh:mm:ss.mmm UTC (date not in log)) |
state |
string | calibrating, nominal, degraded ou untrusted |
score |
número ou null | 0 a 100, uma casa decimal; null durante a calibração ou quando note diz por que nenhuma pôde ser produzida |
deductions |
vetor | {"monitor": string, "ratio": number, "points": number, "class": string}, os de mais pontos primeiro; ratio é a estatística sobre o limiar (alarme em 1 ou mais); só os monitores que custam pontos são listados; class (acrescentado na 1,3) é geometry, environment ou inconsistency |
alarms |
vetor de strings | monitores em seu limiar ou acima dele |
gate |
string | off, passed ou withheld |
note |
string ou nulo | por que nenhuma pontuação foi produzida (por exemplo, um sensor de aproamento declarado que está ausente) |
position |
objeto ou null | (acrescentado na 1,1) a posição que o receptor informou nesta época, {"lat_deg", "lon_deg", "height_m"} (altura elipsoidal quando a sentença dá a separação do geoide, senão acima do nível médio do mar); null quando o receptor não deu nenhuma, inclusive em épocas de calibração sem posição |
advisory |
string | (acrescentado na 1,2) o que este software é e não é: consultivo, não é um equipamento de navegação homologado, o operador continua responsável |
geometry |
objeto | (acrescentado na 1,3) a geometria dos satélites: status (good, degraded, unknown quando o fluxo não tem elevações e azimutes GSV nem GSA), reasons (few-satellites, high-pdop, high-hdop, sky-blocked), source (derived, reported, none), n_used, hdop, pdop, vdop, open_fraction, max_azimuth_gap_deg, age_s, reported_hdop, reported_derived_mismatch, note, in_view, signal_loss (satélites à vista mas não rastreados enquanto o DOP à vista é bom: o desconto de geometria é então environment), label (good, fair, poor, unknown: sempre informado, nunca pontuado; a pontuação desconta apenas por poor) (veja RECEIVER-TRUST.md) |
Nomes de monitores (kebab-case; 17): cn0-drop, agc, jam-ind, loss-of-lock, position-jump, raim, clock, solve-failure, kinematic, heading-course, speed-log, sea-level, cn0-spread, cn0-rise, time-consistency, osnma e, a partir da 1,3, geometry. Novos nomes podem ser acrescentados em versões posteriores; os consumidores devem tratar um nome de monitor desconhecido como um monitor. O leiaute $PKSHT abaixo leva uma versão de formato em seu primeiro campo; este esquema JSON é a versão 1,3: a 1,1 acrescentou position, a 1,2 advisory, a 1,3 geometry no final e class em cada desconto, e só muda acrescentando chaves no final.
Entrada de autenticação#
O monitor osnma recebe o estado de autenticação por satélite de uma fonte de autenticação por meio de MarineObs::sat_auth (uma lista de (satellite, status), estado Authenticated, Failed ou Unavailable), ao lado do MarineObs::osnma geral. Do lado NMEA, o mesmo é levado por $PKSOS,<A|F|N>[,<sat>:<A|F|N>...], por exemplo $PKSOS,A,E11:A,E19:F. Qualquer falha, geral ou em um satélite, aciona o alarme do monitor e custa todo o seu peso (recebe a razão 1,5); o sucesso não é evidência. O Kshana não verifica nada aqui: a fonte que o faz é responsável pelo estado que informa.
Uma época está completa quando chega a próxima sentença com marca de tempo; as sentenças de instrumentos mais lentos ou não sincronizados (um giroscópio alguns décimos de segundo atrás do receptor) que chegam antes disso pertencem a ela. Se o fluxo parar por [live] idle_flush_s (padrão 1,5 s, ajuste-o acima da maior lacuna entre as sentenças com marca de tempo do seu receptor), a época é concluída como está. Os primeiros calibration_s segundos do fluxo formam a linha de base e nunca são pontuados, de modo que um fluxo que já está sendo falsificado quando é conectado pela primeira vez não tem linha de base limpa: inicie a camada antes da viagem, ou enquanto se sabe que a posição é boa. A janela de calibração se fecha uma só vez, por chegada: uma época cujo tempo é anterior a um tempo já visto (um retrocesso, uma repetição do início do fluxo) nunca é calibração, qualquer que seja o seu tempo; é pontuada com um desconto cheio de time-consistency, que é não confiável. O motor ao vivo pontua cada época sobre as épocas de calibração e o último minuto, mais ou menos, do fluxo, de modo que seu custo por época cresce com calibration_s vezes a taxa de épocas; mantenha a janela curta em um receptor rápido. Seus buffers são limitados (uma enxurrada de linhas sem sentença com marca de tempo é concluída a cada 5.000 linhas, e a calibração e o histórico são limitados a 20.000 épocas).
O tempo do receptor também é comparado com o relógio monotônico deste computador, o que só tem sentido para um fluxo que chega em tempo real. Um registro armazenado alimentado em velocidade total por stdin, TCP ou UDP aciona essa verificação por construção: passe --replay. (--file sem --follow já a implica.) Um --file ... --follow é lido como repetição até ser lido até o fim, e o relógio do hospedeiro é acionado a partir daí, de modo que um atraso acumulado não seja lido como falha de relógio; a verificação então precisa que a janela de calibração ainda esteja aberta (caso contrário não tem linha de base e não é executada).
Término e falhas do fluxo: stdin e um arquivo lido até o fim terminam normalmente (saída 0). Uma conexão TCP fechada pelo par não é um término normal para um fluxo que deveria continuar: a camada sai com código diferente de zero depois de pontuar e gravar tudo o que havia recebido e não se reconecta, portanto execute-a sob um supervisor que a reinicie. Os datagramas UDP que dividem uma sentença são unidos; os leitores de stdin, de um arquivo e de TCP são sustentados por uma fila limitada que pressiona o emissor de volta (nada se perde), ao passo que o UDP, que não pode pressionar de volta, descarta os datagramas que o motor não consegue aceitar e avisa em stderr. --udp <port> faz o bind no endereço de loopback; dê --udp <addr>:<port> para escutar em outro lugar (um aviso é impresso).
$PKSHT: a sentença proprietária#
Cada época também produz uma sentença NMEA 0183, com soma de verificação válida, que --pksht <path|-> grava em um arquivo ou em stdout e que o portão insere no fluxo encaminhado:
$PKSHT,1,080140.25,30.0,U,W,heading-course:40.0/cn0-spread:30.0*2F
| Campo | Significado |
|---|---|
| 1 | 1: a versão do formato |
| 2 | hora UTC da época, hhmmss.ss; vazio se o fluxo não deu nenhuma |
| 3 | pontuação de confiança 0 a 100, uma casa decimal; vazio durante a calibração ou quando nenhuma pôde ser produzida |
| 4 | faixa: C em calibração, N nominal, D degradada, U não confiável |
| 5 | portão: - desligado, P passou, W retido (a posição foi marcada como inválida no ciclo encaminhado) |
| 6 | até dois motivos, monitor:points unidos por /; vazio quando nada foi descontado |
O endereço é P + o mnemônico do fabricante KSH + T. Equipamentos que não conhecem uma sentença proprietária a ignoram. O Kshana ignora o seu próprio $PKSHT na entrada.
Modo portão#
--gate coloca o Kshana entre o receptor e o equipamento que usa sua posição (um sistema de cartas, um sistema de controle de rota). O fluxo NMEA entra, sai em stdout e é:
- repassado sem alteração enquanto a época não é não confiável (e durante a calibração), com um
$PKSHTapós cada ciclo de sentenças; e - marcado como inválido enquanto é não confiável: qualidade GGA
0; estado RMCV(e seu indicador de modoNe estado de navegaçãoVonde presentes); modo GNSNem toda posição; estado GLLVe modoN; modo VTGNonde houver. Os campos de posição são deixados como estavam: o objetivo é que o equipamento veja o próprio receptor declarar a posição inválida e acione seu próprio alarme. Toda sentença reescrita tem sua soma de verificação recalculada.
Uma vez retida, a posição só é liberada depois que as épocas ficarem fora da faixa não confiável por [live] gate_release_s (padrão 30 s), de modo que uma pontuação no limite da faixa não possa fazer a posição oscilar. As linhas JSON vão apenas para onde --json <path> indicar (por padrão, para lugar nenhum, porque o fluxo ocupa stdout).
receiver-nmea-source | kshana receiver-trust live session.toml --gate --json trust.jsonl | downstream-equipment
Para deixar um plotter de cartas se conectar diretamente, sirva o fluxo filtrado por TCP em vez de stdout:
receiver-nmea-source | kshana receiver-trust live session.toml --gate --listen tcp:10110
--listen tcp:<port> escuta no endereço de loopback; tcp:<addr>:<port> escuta em outro lugar (um aviso é impresso, porque quem alcançar o endereço pode ler o fluxo). Qualquer número de clientes pode se conectar; cada um recebe o mesmo fluxo a partir do instante em que se conecta, e os clientes só leem. Cada cliente tem sua própria fila limitada e seu próprio escritor, de modo que um que não consegue acompanhar é descartado (sua conexão é fechada, uma linha em stderr) e nunca atrasa os outros nem a entrada. --listen precisa de --gate; stdout então não leva nada do fluxo, portanto --json - fica livre.
O que o portão não faz e o que saber antes de usá-lo:
- É opcional. Nada marca uma posição como inválida a menos que
--gateseja dado. - Ele acrescenta latência: um ciclo fica retido até que sua época seja pontuada, o que leva o tempo até a próxima sentença com marca de tempo (cerca de um ciclo: um segundo para um receptor de 1 Hz), ou
idle_flush_sapós a última quando o fluxo trava. Equipamentos que precisam de uma sentença a poucas dezenas de milissegundos da saída do receptor não devem ficar atrás dele. - É um ponto único na cadeia: se ele para, o fluxo para. Execute-o sob supervisão e decida de antemão o que o equipamento a jusante faz sem um fluxo.
- Ele falha em modo fechado diante de suas próprias falhas: se os monitores não conseguem produzir uma pontuação após a calibração (um sensor de aproamento declarado que não envia nada, épocas de calibração insuficientes), a época é não confiável, leva uma
notee é retida; a retenção de liberação é contada pelo relógio deste computador, não pelo tempo do receptor, que é o que um falsificador controla (para uma repetição só há o tempo do receptor). - Ele pode reter uma boa posição (um alarme falso) assim como deixar passar uma falsificada (uma omissão). Os monitores conferem uma posição com a física de um navio e seus outros sensores; uma falsificação que seja consistente com todos eles não é vista (veja os limites abaixo).
- Ele espera um fluxo de texto NMEA 0183 puro. Quadros binários misturados ao fluxo são encaminhados sem alteração, mas um
$PKSHTpode então cair entre os bytes de um quadro. - Ele não é homologado e nada nele foi avaliado segundo a IEC 61108 ou a IEC 61162. O operador continua responsável pela navegação da embarcação.