ILRBCSim
ADR-029 Interlocking simulator — grants/extends Movement Authority against the RBC wire protocol
Loading...
Searching...
No Matches
il.il_sim Namespace Reference

Functions

 _is_keepalive (data)
 main ()

Variables

float ROUTE_STATUS_PERIOD_S = 2.0
dict _CMD_ROUTE_TYPE_NAME = {il_wire.ROUTE_TYPE_NO_ROUTE: "NoRoute", il_wire.ROUTE_TYPE_LOCKED: "Locked"}
dict _CMD_ROUTE_STATUS_NAME
 CATALOG = MessageCatalog(os.path.join(os.path.dirname(os.path.abspath(__file__)), "message_catalog.json"))
int _RELAY_KEEPALIVE_KIND = 9

Detailed Description

Interlocking (IL) sim (ADR-029) - a real, dual-homed TCP client that
sets/releases routes for one train's session, ON COMMAND from a test
harness (tests/robot/) rather than a fixed wall-clock schedule - see
control_server.py's own header for the command channel design. Dual-homed
the same way train_sim.py is (see dual_link.py's own header) - sends
ROUTE_ADD/ROUTE_RELEASE to both sites unconditionally, since only
whichever site is currently ONLINE will actually act on it.

IL<->RBC route-identity pass: routes are now identified on the wire by
their own (start_signal, end_signal) pair (the real signal pair a route
runs between - see rbc_wire_types.h's own doc), not a synthetic id, and
IL now genuinely RECEIVES something meaningful too -
TrainPositionInRoute, RBC's own report of whether a route currently has
a train authorized through it. Before this pass IL was send-only in
practice (see this file's own git history) - the main loop's own
poll_recv() drained and ignored everything; it now decodes real inbound
messages the same way train_sim.py/ctc_sim.py already do.

Configuration: one JSON file (common/sim_config.py, SIM_CONFIG_PATH env
var, default /app/config.json) supplies everything instance-specific -
trainIndex (0 or 1, selects which of this project's
SAFEAPI_EXAMPLE_MAX_TRAINS train slots this IL instance sets routes for -
train_id is trainIndex + 1; il-west sets routes for train-west's session,
il-east for train-east's, by this shared convention - ADR-029),
siteTag, rbcWest/rbcEast, controlServer, and routeLengthM (the default
ADD_ROUTE grant, replaces the old RBC_ROUTE_LENGTH_M constant). See
sims/il/config/*.json for the actual files. Message vocabulary comes
from message_catalog.json, right next to this script.

Commands (controlServer.port, config file - see common/control_server.py):
  ADD_ROUTE [length_m]   Sends one ROUTE_ADD (default length
                         config's own routeLengthM if omitted) - no route
                         identity, see this handler's own doc for why
                         that's a real limitation now. Replies "OK\\n".
  PING                   Replies "PONG\\n" - liveness check for a test
                         harness before it starts asserting anything.
  SET_IL_STATUS <s>      Sets + sends this IL's own RBC_MSG_IL_STATUS
                         (s = down|restarting|up). IL announces "up" at
                         startup and re-announces every
                         ROUTE_STATUS_PERIOD_S; this overrides it for
                         tests of the RBC's DOWN/RESTARTING handling.
                         Replies "OK\\n".

Structured JSON commands (tests/robot/design/DESIGN.md,
SIM_INTERFACES.md - same port, see common/control_server.py's own doc):
  sendMessage   {"cmd":"sendMessage","nidEngine":N,"message":"ROUTE_ADD",
                 "fields":{"route_len":500,"start_signal":100,
                           "end_signal":101,"route_type":0}}
                Sends one ROUTE_ADD/ROUTE_RELEASE/etc NOW with the given
                fields - the structured equivalent of ADD_ROUTE above
                (route_len defaults to config's own routeLengthM if the
                field is left unset for ROUTE_ADD, same as ADD_ROUTE's
                own default behavior; route identity fields have no
                default - the caller must supply them for a real grant).
                message "IL_ROUTE_CMD" / "IL_STATUS" use the dedicated
                packed IL protocol (il_wire.py, mirrors ab_ga_il_wire.h)
                instead of the flat codec: IL_ROUTE_CMD fields
                route_type/route_status/degraded_status/
                release_route_request/first_route_in_path (enum ints,
                first value = default) + route_id/start_signal/end_signal
                (-1 = unset); IL_STATUS field il_status (0/1/2).
  getMessage    {"cmd":"getMessage","nidEngine":N,"message":"TrainPositionInRoute"}
                Returns the most recently received packet of that kind
                for that nidEngine, or an ERR if none has arrived yet -
                same "most recent value, not a queue" contract
                train_sim.py's own getMessage already has (DESIGN.md
                section 4.2).

Function Documentation

◆ _is_keepalive()

_is_keepalive ( data)
protected

Definition at line 115 of file il_sim.py.

◆ main()

main ( )

Definition at line 119 of file il_sim.py.

Variable Documentation

◆ _CMD_ROUTE_STATUS_NAME

dict il.il_sim._CMD_ROUTE_STATUS_NAME
protected
Initial value:
= {
il_wire.ROUTE_STATUS_NO_STATUS: "NoStatus", il_wire.ROUTE_STATUS_FS: "FS",
il_wire.ROUTE_STATUS_OS: "OS", il_wire.ROUTE_STATUS_SH: "SH",
il_wire.ROUTE_STATUS_USED: "Used", il_wire.ROUTE_STATUS_DEGRADED: "Degraded",
}

Definition at line 94 of file il_sim.py.

◆ _CMD_ROUTE_TYPE_NAME

dict il.il_sim._CMD_ROUTE_TYPE_NAME = {il_wire.ROUTE_TYPE_NO_ROUTE: "NoRoute", il_wire.ROUTE_TYPE_LOCKED: "Locked"}
protected

Definition at line 93 of file il_sim.py.

◆ _RELAY_KEEPALIVE_KIND

int il.il_sim._RELAY_KEEPALIVE_KIND = 9
protected

Definition at line 112 of file il_sim.py.

◆ CATALOG

il.il_sim.CATALOG = MessageCatalog(os.path.join(os.path.dirname(os.path.abspath(__file__)), "message_catalog.json"))

Definition at line 100 of file il_sim.py.

◆ ROUTE_STATUS_PERIOD_S

float il.il_sim.ROUTE_STATUS_PERIOD_S = 2.0

Definition at line 89 of file il_sim.py.