ILRBCSim
ADR-029 Interlocking simulator — grants/extends Movement Authority against the RBC wire protocol
Loading...
Searching...
No Matches
il_wire.py
Go to the documentation of this file.
1"""Byte-identical Python mirror of safeAPIRBC2oo2GA/src/AB/il/ab_ga_il_wire.h -
2the dedicated IL <-> RBC messages (wire kinds 25/26/27).
3
4These do NOT use SimCore's generic flat 96-byte envelope codec
5(rbc_wire.py / MessageCatalog); each has its own small packed layout,
6still shipped inside the fixed 96-byte relay slot (rest zero). Keep this
7in exact lockstep with ab_ga_il_wire.h - there is no shared schema, same
8"by-hand port" precedent as SimCore/rbc_wire.py for the flat scheme and
9TrainRBCSim/rbc_ertms_wire.py for the ERTMS scheme.
10
11All multi-byte fields little-endian. See ab_ga_il_wire.h for the
12authoritative byte-offset table.
13"""
14
15import struct
16
17from simcore.rbc_wire import ENVELOPE_SIZE
18
19# ---- wire kinds (rbc_wire_types.h) ---------------------------------------
20KIND_IL_ROUTE_CMD = 25
21KIND_IL_STATUS = 26
22KIND_IL_ROUTE_INDICATION = 27
23
24# ---- enum values (rbc_wire_types.h, rbc_il_* enums) --------------------
25ROUTE_TYPE_NO_ROUTE = 0
26ROUTE_TYPE_LOCKED = 1
27
28ROUTE_STATUS_NO_STATUS = 0
29ROUTE_STATUS_FS = 1
30ROUTE_STATUS_OS = 2
31ROUTE_STATUS_SH = 3
32ROUTE_STATUS_USED = 4
33ROUTE_STATUS_DEGRADED = 5
34
35DEGRADED_STATUS_NO_STATUS = 0
36DEGRADED_STATUS_LOW = 1
37DEGRADED_STATUS_MEDIUM = 2
38DEGRADED_STATUS_HIGH = 3
39
40IL_STATUS_DOWN = 0
41IL_STATUS_RESTARTING = 1
42IL_STATUS_UP = 2
43
44EMERGENCY_TYPE_NONE = -1
45EMERGENCY_TYPE_SAM = 0
46EMERGENCY_TYPE_CEM = 1
47EMERGENCY_TYPE_UEM = 2
48
49_NAME_BY_KIND = {
50 KIND_IL_ROUTE_CMD: "IL_ROUTE_CMD",
51 KIND_IL_STATUS: "IL_STATUS",
52 KIND_IL_ROUTE_INDICATION: "IL_ROUTE_INDICATION",
53}
54
55
56def _slot(payload):
57 """Zero-pads @payload out to the full 96-byte relay slot."""
58 if len(payload) > ENVELOPE_SIZE:
59 raise ValueError("IL message payload exceeds the relay slot")
60 return payload + b"\x00" * (ENVELOPE_SIZE - len(payload))
61
62
63def encode_route_cmd(route_type=ROUTE_TYPE_NO_ROUTE, route_status=ROUTE_STATUS_NO_STATUS,
64 degraded_status=DEGRADED_STATUS_NO_STATUS, release_route_request=0,
65 first_route_in_path=0, route_id=-1, start_signal=-1, end_signal=-1):
66 """RBC_MSG_IL_ROUTE_CMD (IL -> RBC). Fields default to the SPEC
67 defaults ("first value is default value"). route_id/start_signal/
68 end_signal are int32, -1 = unset."""
69 body = struct.pack(
70 "<BBBBBBBB iii",
71 KIND_IL_ROUTE_CMD,
72 0, # reserved
73 route_type & 0xFF,
74 route_status & 0xFF,
75 degraded_status & 0xFF,
76 1 if release_route_request else 0,
77 1 if first_route_in_path else 0,
78 0, # reserved
79 int(route_id), int(start_signal), int(end_signal),
80 )
81 return _slot(body)
82
83
84def encode_il_status(il_status=IL_STATUS_DOWN):
85 """RBC_MSG_IL_STATUS (IL -> RBC)."""
86 body = struct.pack("<BBH", KIND_IL_STATUS, il_status & 0xFF, 0)
87 return _slot(body)
88
89
91 """RBC_MSG_IL_ROUTE_INDICATION (RBC -> IL) -> flat dict, or None if
92 @frame is not this kind / too short. emergency_type is a SIGNED byte
93 (-1 = none). route_fsm_state is ab_ga_route_state_t (0..6:
94 NO_ROUTE/LOCKED/FS/OS/SH/USED/DEGRADED)."""
95 if len(frame) < 24 or frame[0] != KIND_IL_ROUTE_INDICATION:
96 return None
97 (_kind, _rsv1, train_in_route, train_has_ma_in_route, emergency_in_route,
98 emergency_type_i8, route_fsm_state, route_fsm_is_stub) = struct.unpack_from("<BBBBBbBB", frame, 0)
99 route_id, start_signal, end_signal, allocated_train_nid_engine = struct.unpack_from("<iiii", frame, 8)
100 return {
101 "route_id": route_id,
102 "start_signal": start_signal,
103 "end_signal": end_signal,
104 "allocated_train_nid_engine": allocated_train_nid_engine,
105 "train_in_route": int(bool(train_in_route)),
106 "train_has_ma_in_route": int(bool(train_has_ma_in_route)),
107 "emergency_in_route": int(bool(emergency_in_route)),
108 "emergency_type": emergency_type_i8,
109 "route_fsm_state": route_fsm_state,
110 "route_fsm_is_stub": int(bool(route_fsm_is_stub)),
111 }
112
113
114ROUTE_FSM_STATE_NAMES = ["NO_ROUTE", "LOCKED", "FS", "OS", "SH", "USED", "DEGRADED"]
115
116
118 return ROUTE_FSM_STATE_NAMES[v] if 0 <= v < len(ROUTE_FSM_STATE_NAMES) else "#%d" % v
119
120
121def kind_name(kind_byte):
122 return _NAME_BY_KIND.get(kind_byte)
kind_name(kind_byte)
Definition il_wire.py:121
route_fsm_state_name(v)
Definition il_wire.py:117
encode_route_cmd(route_type=ROUTE_TYPE_NO_ROUTE, route_status=ROUTE_STATUS_NO_STATUS, degraded_status=DEGRADED_STATUS_NO_STATUS, release_route_request=0, first_route_in_path=0, route_id=-1, start_signal=-1, end_signal=-1)
Definition il_wire.py:65
encode_il_status(il_status=IL_STATUS_DOWN)
Definition il_wire.py:84
_slot(payload)
Definition il_wire.py:56
decode_route_indication(frame)
Definition il_wire.py:90