app.ndtp.server

NDTP TCP server: accepts terminal connections and turns their byte streams into navigation fixes.

Each terminal (or emulated unit) opens its own TCP connection, sends a handshake, then realtime packets. For every realtime packet with a G6CellNav00 the server puts an NdtpFix on the sink queue. Everything after that — unit → vehicle mapping, dataset clock, schedule matching — belongs to the consumer, not here.

Robustness rules (criterion 5: no crash on link loss, recover after reconnect):

  • a slow consumer never blocks socket reads: fixes go in with put_nowait, overflow is dropped and counted in stats.fixes_dropped;

  • a new handshake for a unit closes that unit’s older connection (newest wins — a terminal that reconnected after a network loss leaves a half-open socket behind);

  • connections silent for idle_timeout seconds are closed;

  • framing and decode errors are counted, never fatal to the connection.

The server sends nothing back: the spec defines no acknowledgement packet, and the emulator ignores whatever the server writes.

Classes

NdtpFix(unit_id, nav, received_at, conn_id, ...)

A navigation fix as received: who sent it, what it says, when it arrived.

NdtpServer(sink, *[, host, port, ...])

Asyncio TCP server for NDTP terminals.

ServerStats([connections_total, ...])

class app.ndtp.server.NdtpFix(unit_id: int, nav: NavCell, received_at: float, conn_id: int, request_id: int)[исходный код]

Базовые классы: object

A navigation fix as received: who sent it, what it says, when it arrived.

__init__(unit_id: int, nav: NavCell, received_at: float, conn_id: int, request_id: int) → None
conn_id: int
nav: NavCell
received_at: float
request_id: int
unit_id: int
class app.ndtp.server.NdtpServer(sink: Queue[NdtpFix], *, host: str = '0.0.0.0', port: int = 9201, idle_timeout: float = 300.0, max_connections: int = 20000, backlog: int = 4096)[исходный код]

Базовые классы: object

Asyncio TCP server for NDTP terminals. start() binds, stop() closes everything.

__init__(sink: Queue[NdtpFix], *, host: str = '0.0.0.0', port: int = 9201, idle_timeout: float = 300.0, max_connections: int = 20000, backlog: int = 4096) → None[исходный код]
snapshot() → dict[исходный код]

State for /health and metrics.

async start() → None[исходный код]
async stop() → None[исходный код]
class app.ndtp.server.ServerStats(connections_total: 'int' = 0, connections_rejected: 'int' = 0, connections_superseded: 'int' = 0, connections_idle_closed: 'int' = 0, handshakes: 'int' = 0, fixes: 'int' = 0, fixes_dropped: 'int' = 0, frames_without_nav: 'int' = 0, frames_before_handshake: 'int' = 0, unknown_messages: 'int' = 0, decode_errors: 'int' = 0)[исходный код]

Базовые классы: object

__init__(connections_total: int = 0, connections_rejected: int = 0, connections_superseded: int = 0, connections_idle_closed: int = 0, handshakes: int = 0, fixes: int = 0, fixes_dropped: int = 0, frames_without_nav: int = 0, frames_before_handshake: int = 0, unknown_messages: int = 0, decode_errors: int = 0) → None
connections_idle_closed: int
connections_rejected: int
connections_superseded: int
connections_total: int
decode_errors: int
fixes: int
fixes_dropped: int
frames_before_handshake: int
frames_without_nav: int
handshakes: int
unknown_messages: int