SimCore
Shared transport-layer plumbing for the ADR-029 Train/IL/CTC RBC simulators
Loading...
Searching...
No Matches
simcore.rbc_messages Namespace Reference

Classes

class  UnknownMessageError
class  UnknownFieldError
class  InvalidFieldValueError
class  WrongDirectionError
class  MessageCatalog

Functions

 _validate_value (message, field, spec, value)

Detailed Description

Structured message layer on top of rbc_wire.py's raw envelope codec
(safeAPITestEnv/doc/design/DESIGN.md) - translates between the JSON
sendMessage/getMessage control-port commands (control_server.py) and
real rbc_envelope_t bytes (rbc_wire.py). rbc_wire.py itself is
deliberately untouched by this module (DESIGN.md section 6 - "what does
NOT change") - this is a new layer above it, not a replacement: every
sim still sends/receives the exact same wire bytes it always has, this
module only adds a named, field-validated way to build/decode them.

The message/packet/field vocabulary itself is DATA, not code - loaded
from each sim's own message_catalog.json (sims/train/, sims/il/,
sims/ctc/ - NOT one shared catalog, deliberately: a sim's own catalog
only lists the messages THAT sim actually sends/receives, e.g. il's
never mentions M3 at all since IL neither sends nor receives it - see
each catalog file's own header). Adding/adjusting a message's fields or
allowed values is a JSON edit, not a Python change.

MessageCatalog is a class, not a module-level singleton, specifically
so each sim can load its OWN catalog file independently - see this
module's previous, single-shared-catalog version's own history if
comparing; that shape did not allow one sim's catalog to differ from
another's, which is exactly what per-sim catalogs need.

**Two coexisting wire families, per-message "wireFormat"** (added
alongside the original flat scheme, not replacing it - the existing
08-18 Robot suite still depends on the flat family working exactly as
before): a message with no "wireFormat" key (every pre-existing catalog
entry) or `"wireFormat": "flat"` uses the original path (rbc_wire.py,
kind-based, always ENVELOPE_SIZE bytes, generic and shared - SimCore
owns the shape, no sim-specific knowledge needed). `"wireFormat": "ertms"`
uses a real Subset-026 codec instead - genuinely variable length,
message-specific shapes (Packet 15/21/27 for an MA, Packet 3/57/58/65/66
for a General Message, etc.), which is Subset-026-the-Train-RBC-air-gap-
protocol specifically - IL and CTC never speak it in this codebase (same
"a sim's own catalog only lists the messages THAT sim uses" principle
above), so unlike rbc_wire.py this is NOT something SimCore can own
generically. **This module stays sim-agnostic**: it does not import any
ertms codec itself - a caller whose OWN catalog declares "ertms"
messages must inject two things at construction time:
  - `ertms_codec`: the codec module (e.g. TrainRBCSim's own
    rbc_ertms_wire.py) - exposes decode(buf) -> (nid_message, decoded_dict).
  - `ertms_encoders`: {catalog_message_name: (nid_engine, fields_dict,
    t_train) -> bytes} - one small adapter per message this sim sends,
    mapping ITS OWN flat {field: int} fields dict (the same shape every
    JSON sendMessage command already uses for the flat scheme) onto the
    codec's own per-message-shaped encode_msg_*() signature.
  - `ertms_flatteners`: {nid_message: decoded_dict -> flat_fields_dict} -
    one small adapter per message this sim receives, flattening the
    codec's own rich nested decode() output into the same flat
    {field: value} shape decode_to_message() already returns for the
    flat scheme.
Both default to empty/None - a catalog with no "ertms" messages (IL's,
CTC's) never needs any of this. Wire bytes for both families are wrapped
identically by one shared outer kind, declared once per catalog file as
a top-level `"_ertmsWrapperKind"` key (RBC_MSG_ERTMS_ENVELOPE=22 today -
moved from 21 after a real collision with a catalog's own flat
TRAIN_CONNECT=21, see __init__()'s own comment on the default below) -
kept catalog-data-driven like every other kind number this module
touches, never hardcoded here (see this module's own precedent for
`kind`/`nidMessage` above), read once at load time, absent/None if a
catalog defines no "ertms" messages at all.

Function Documentation

◆ _validate_value()

_validate_value ( message,
field,
spec,
value )
protected

Definition at line 429 of file rbc_messages.py.