RTE RBC 2oo2 Reference Application 0.1.0 build 0006685
SIL 4 2oo2 Dual-Site Fault-Tolerant ERTMS Radio Block Centre Reference Architecture
Loading...
Searching...
No Matches
ab_gp_proc_dispatch.c
Go to the documentation of this file.
1
5
7
17
18#include "rte/oal/memory/rte_mem_util.h"
19#include "rte/oal/log/rte_log.h"
20
27
29{
30 switch (in->nid_message)
31 {
32 case RBC_MSG_TRAIN_TO_TRACK_VALIDATED_TRAIN_DATA: return in->payload.msg_129.header.t_train;
33 case RBC_MSG_TRAIN_TO_TRACK_REQUEST_FOR_SHUNTING: return in->payload.msg_130.header.t_train;
34 case RBC_MSG_TRAIN_TO_TRACK_MA_REQUEST: return in->payload.msg_132.header.t_train;
35 case RBC_MSG_TRAIN_TO_TRACK_POSITION_REPORT: return in->payload.msg_136.header.t_train;
36 case RBC_MSG_TRAIN_TO_TRACK_ACKNOWLEDGEMENT: return in->payload.msg_146.header.t_train;
37 case RBC_MSG_TRAIN_TO_TRACK_ACK_EMERGENCY_STOP: return in->payload.msg_147.header.t_train;
38 case RBC_MSG_TRAIN_TO_TRACK_END_OF_MISSION: return in->payload.msg_150.header.t_train;
39 case RBC_MSG_TRAIN_TO_TRACK_INIT_SESSION: return in->payload.msg_155.header.t_train;
40 case RBC_MSG_TRAIN_TO_TRACK_TERMINATE_SESSION: return in->payload.msg_156.header.t_train;
41 case RBC_MSG_TRAIN_TO_TRACK_SESSION_ESTABLISHED: return in->payload.msg_159.header.t_train;
42 default: return 0U;
43 }
44}
45
57static bool build_and_stage_reply(ab_gp_channel_handle_t channel, uint8_t train_id,
58 const rbc_train_outbound_msg_t *out_msg)
59{
60 uint8_t frame[RBC_TRAIN_ENVELOPE_WIRE_SIZE];
61 size_t codec_bytes = 0U;
62 rte_status_t status;
64
65 rte_mem_set(frame, 0, sizeof(frame));
66 frame[0] = (uint8_t)RBC_MSG_ERTMS_ENVELOPE;
67 frame[1] = train_id;
68
69 if (!rbc_train_codec_encode_track_to_train(out_msg, &frame[2], sizeof(frame) - 2U, &codec_bytes))
70 {
71 return false;
72 }
73
74 saf = ab_gp_channel_saf_train(channel);
75 if ((saf != NULL) && saf->enabled)
76 {
77 /* REQ-SC-001/004: with the train link protected, a reply goes out only as a Sa-DATA frame of the train's
78 * safe connection - never unprotected. No connection in DATA (or a PDU too large) drops it. */
79 uint8_t saf_frame[AB_GP_SAF_FRAME_MAX];
80 size_t saf_len = 0U;
81
82 if (!ab_gp_saf_train_wrap(saf, train_id, &frame[2], codec_bytes, saf_frame, sizeof(saf_frame), &saf_len) ||
83 !ab_gp_saf_envelope_encode(train_id, saf_frame, saf_len, frame))
84 {
85 return false;
86 }
87 }
88
89 status = ab_gp_channel_stage_relay(channel, RTE_EXAMPLE_RELAY_KIND_TRAIN, 0U, frame, sizeof(frame));
90 return (status == RTE_STATUS_OK);
91}
92
102{
103 rte_mem_set(m24, 0, sizeof(*m24));
107 m24->header.nid_lrbg.nid_bg = (uint16_t)nid_engine;
108
109 m24->has_national_values = true;
110 m24->national_values.v_nvshunt = 30U;
111 m24->national_values.v_nvstff = 40U;
112 m24->national_values.v_nvunfit = 100U;
113 m24->national_values.t_nvcontact = 10U;
114 m24->national_values.d_nvroll = 2U;
115
116 m24->has_ma_request_params = true;
117 m24->ma_request_params.t_mar_s = 5U;
118 m24->ma_request_params.d_mar_m = 100U;
119
120 m24->has_pr_params = true;
121 m24->pr_params.t_cycloc_s = 2U;
122 m24->pr_params.d_cycloc_m = 0U;
123}
124
126 uint8_t train_id, ab_gp_ertms_train_context_t *ctx,
127 const rbc_msg_155_init_session_t *m155, uint32_t cycle, uint32_t timestamp_ms)
128{
130
131 /* Previously set by ab_gp_ertms_engine_step()'s own now-removed
132 * auto-drive (off db_connected alone) - now set here, from the real
133 * Msg 155 that actually identifies the train, the first point this
134 * context has one to record. */
135 ctx->nid_engine = m155->header.nid_engine;
136 ctx->train_data.valid = false;
137 ctx->train_data.config_sent = false;
139 (void)ab_gp_proc_session_handle_initiation(ctx, cycle, timestamp_ms);
140 /* This project's own simplified flow has no separate train-side
141 * confirmation round trip before Full Supervision work can begin
142 * (unlike the real protocol's own Msg 159) - drive straight to
143 * ESTABLISHED once RBC's own accept is about to go out. */
144 (void)ab_gp_proc_session_handle_established(ctx, 0U, timestamp_ms);
145
146 if (session != NULL)
147 {
148 if (!session->in_use)
149 {
150 rte_mem_set(session, 0, sizeof(*session));
151 session->in_use = true;
152 session->train_id = train_id;
153 }
154 /* A new session starts a new CTC notification cycle (CTC_CONNECTED, then CTC_MA_GRANTED for its first MA)
155 * even when the slot stayed in_use across the previous End of Mission (routes still held): otherwise the first
156 * MA of this mission reaches CTC as CTC_MA_EXTENDED with ma_seq 1 - seen on both MA paths (the ERTMS MA
157 * request and GA's route-connect grant), ISS-009. */
158 session->ctc_connected_sent = false;
159 session->ctc_ma_granted_sent = false;
160 }
161 if (db != NULL)
162 {
163 (void)ab_gp_train_handle_connect(db, train_id);
164 }
165
166 rte_mem_set(&reply, 0, sizeof(reply));
169 reply.payload.msg_24.header.t_train = s_reply_t_train;
170 reply.payload.msg_24.header.m_ack = RBC_M_ACK_NOT_REQUIRED;
171 reply.payload.msg_24.header.nid_lrbg.nid_bg = (uint16_t)m155->header.nid_engine;
172 /* Bare accept - no packets yet; Packet 3/57/58 ride the LATER Msg 24
173 * once train data + first position are both in (see handle_msg_136). */
174 (void)build_and_stage_reply(channel, train_id, &reply);
175}
176
178 uint8_t train_id, uint32_t timestamp_ms)
179{
180 (void)ctx; /* validate_train_data() reaches the same context internally via train_id */
181 (void)ab_gp_ertms_validate_train_data(train_id, m129->l_train, (uint32_t)m129->v_maxtrain,
182 m129->m_axleload, m129->m_loadinggauge, m129->m_airtight,
183 timestamp_ms);
184}
185
188static void handle_msg_130(ab_gp_channel_handle_t channel, uint8_t train_id, ab_gp_ertms_train_context_t *ctx,
189 const rbc_msg_130_request_for_shunting_t *m130, uint32_t cycle, uint32_t timestamp_ms)
190{
194
195 (void)ab_gp_ertms_update_train_position(train_id, pos->nid_lrbg.nid_bg, pos->d_lrbg,
196 pos->q_dirlrbg,
197 (uint32_t)pos->v_train, (uint32_t)pos->m_mode,
198 (uint32_t)pos->m_level, cycle, timestamp_ms);
199
200 decision = ab_gp_proc_shunting_handle_request(ctx, train_id, (uint32_t)pos->v_train);
201 RTE_EXAMPLE_LOG("cycle %u: ERTMS Msg 130 train %u: SH %s\n", cycle, (unsigned int)train_id,
203
204 (void)ab_gp_proc_shunting_build_reply(decision, s_reply_t_train, m130->header.t_train, pos->nid_lrbg, &reply);
205 if (!build_and_stage_reply(channel, train_id, &reply))
206 {
207 RTE_EXAMPLE_LOG("cycle %u: ERTMS Msg %u to train %u could not be staged\n", cycle,
208 (unsigned int)reply.nid_message, (unsigned int)train_id);
209 }
210}
211
213 uint8_t train_id, ab_gp_ertms_train_context_t *ctx,
214 const rbc_msg_136_position_report_t *m136, uint32_t cycle, uint32_t timestamp_ms)
215{
218 /* A Packet-1 report while the session is already IDLE is the new
219 * post-EoM idle heartbeat (see TrainRBCSim's own 6s Packet-1 cadence) -
220 * a pure liveness ping, not a re-connect signal. Everything else
221 * (Packet 0 at any session state, or a Packet-1 report arriving while
222 * a session IS active/established) keeps today's exact behaviour:
223 * session->in_use resurrection + db connect/position-report side
224 * effects still fire, same as before this field existed. */
225 const bool is_idle_heartbeat = m136->has_packet1 && (ctx->session_state == AB_GP_ERTMS_SESSION_IDLE);
226
227 (void)ab_gp_ertms_update_train_position(train_id, pos->nid_lrbg.nid_bg, pos->d_lrbg,
228 pos->q_dirlrbg,
229 (uint32_t)pos->v_train, (uint32_t)pos->m_mode,
230 (uint32_t)pos->m_level, cycle, timestamp_ms);
231
232 if (!is_idle_heartbeat)
233 {
234 if (session != NULL)
235 {
236 if (!session->in_use)
237 {
238 rte_mem_set(session, 0, sizeof(*session));
239 session->in_use = true;
240 session->train_id = train_id;
241 }
242 /* Deliberately NOT session->cycle = cycle here: that field's own
243 * doc is "Last M136 cycle number seen for this train" - the
244 * FLAT scheme's own M136 handler (ab_gp_train.c) fills it from
245 * env->cycle, a field the TRAIN itself reports on the wire. Real
246 * Subset-026's own Msg 136/Packet 0 has no equivalent counter at
247 * all, so there is nothing train-reported to put here - writing
248 * this function's own @p cycle (GP's cyclic-executive count,
249 * ctx->cyc_cycle) instead would silently give the field a
250 * different, GP-side meaning depending on which scheme last
251 * touched it (found live, not yet consequential: nothing
252 * currently reads this field back for an ERTMS-managed session -
253 * ab_gp_train_build_position_answer(), the one real reader, is
254 * only ever called from the flat scheme's own output path). */
255 session->d_lrbg = pos->d_lrbg;
256 }
257 if (db != NULL)
258 {
259 (void)ab_gp_train_handle_connect(db, train_id);
260 (void)ab_gp_train_handle_position_report(db, train_id, pos->nid_lrbg.nid_bg);
261 }
262 }
263
264 rte_mem_set(&reply, 0, sizeof(reply));
266 if (ctx->train_data.valid && !ctx->train_data.config_sent)
267 {
268 /* FR-RBC-SOM-003: first Msg 24 after train data + first position
269 * report both arrived - confirms train data and injects config
270 * packets. */
271 build_config_msg_24(&reply.payload.msg_24, m136->header.nid_engine);
272 ctx->train_data.config_sent = true;
273 }
274 else
275 {
276 /* FR-RBC-EOM-002 / Phase 2 cyclic ack: bare acknowledgement of a
277 * later position report, no packets. */
279 reply.payload.msg_24.header.t_train = s_reply_t_train;
280 reply.payload.msg_24.header.m_ack = RBC_M_ACK_NOT_REQUIRED;
281 reply.payload.msg_24.header.nid_lrbg.nid_bg = (uint16_t)m136->header.nid_engine;
282 }
283 (void)build_and_stage_reply(channel, train_id, &reply);
284}
285
287 uint8_t train_id, ab_gp_ertms_train_context_t *ctx)
288{
289 uint16_t held_routes[RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN];
290 uint8_t held_count = 0U;
291 uint16_t route_id = 0U;
292 uint8_t i;
293 uint8_t j;
294 bool found = false;
295 bool fresh_ma;
297
298 if (!ab_gp_db_train_get_routes(db, train_id, held_routes, &held_count))
299 {
300 return;
301 }
302
303 /* First IL-granted route this train holds that isn't already
304 * reflected in its own active MA - matches this codebase's own
305 * "IL grants/locks, GP turns an already-granted route into an MA"
306 * split (ab_ga_il.c's handle_route_add() is untouched by this). */
307 for (i = 0U; (i < held_count) && !found; i++)
308 {
309 bool already_in_ma = false;
310 for (j = 0U; j < ctx->ma.route_count; j++)
311 {
312 if (ctx->ma.route_ids[j] == held_routes[i])
313 {
314 already_in_ma = true;
315 break;
316 }
317 }
318 if (!already_in_ma)
319 {
320 route_id = held_routes[i];
321 found = true;
322 }
323 }
324
325 if (!found)
326 {
327 return;
328 }
329
330 fresh_ma = !ctx->ma.has_active_ma;
331 if (fresh_ma)
332 {
333 if (!ab_gp_ertms_calc_ma_for_route(train_id, route_id, 1U))
334 {
335 return;
336 }
337 }
338 else
339 {
340 if (!ab_gp_ertms_extend_ma_for_route(train_id, route_id))
341 {
342 return;
343 }
344 }
345
346 if (session != NULL)
347 {
348 session->granted_length = (uint32_t)ctx->ma.p15.ma_length;
349 session->ma_seq = ctx->ma.ma_seq;
350 /* Deliberately ctc_ma_notify_pending, NOT ma_pending_send: this
351 * handler already sends its own RBC_MSG_ERTMS_ENVELOPE-wrapped
352 * Msg 3 below (build_and_stage_reply()) - setting ma_pending_send
353 * here too would make ab_gp_train_build_outputs() (the FLAT
354 * scheme's own output builder) ALSO build and stage a duplicate
355 * flat-kind M3 as an unwanted side effect (found live: every
356 * real ERTMS grant was silently also emitting a second, flat M3
357 * on the same Train relay channel, which train_sim.py's own
358 * receive loop then auto-acked with an unrelated flat Msg 146).
359 * ab_ga_ctc_build_outputs() (GA) checks this flag in addition to
360 * ma_pending_send specifically so CTC still gets its
361 * CTC_MA_GRANTED/_EXTENDED indication - see that function's own
362 * comment and ab_gp_train_session_t's own doc on this flag. */
363 session->ctc_ma_notify_pending = true;
364 /* CTC is told GRANTED vs EXTENDED by the same decision made above (fresh MA vs extension), not by a latch
365 * that can outlive the mission: a session slot kept in_use across an End of Mission (routes still held,
366 * see the EoM case below) kept ctc_ma_granted_sent from the previous mission, so the next mission's first
367 * MA (ma_seq 1) was reported as CTC_MA_EXTENDED (ISS-009). */
368 if (fresh_ma)
369 {
370 session->ctc_ma_granted_sent = false;
371 }
372 }
373
374 rte_mem_set(&reply, 0, sizeof(reply));
377 reply.payload.msg_3.header.t_train = s_reply_t_train;
378 reply.payload.msg_3.header.m_ack = RBC_M_ACK_REQUIRED;
379 reply.payload.msg_3.ma = ctx->ma.p15;
380 reply.payload.msg_3.has_gradient = (ctx->ma.p21.segment_count > 0U);
381 reply.payload.msg_3.gradient = ctx->ma.p21;
382 reply.payload.msg_3.has_ssp = (ctx->ma.p27.segment_count > 0U);
383 reply.payload.msg_3.ssp = ctx->ma.p27;
384 reply.payload.msg_3.has_linking = (ctx->ma.p5.link_count > 0U);
385 reply.payload.msg_3.linking = ctx->ma.p5;
386
387 (void)build_and_stage_reply(channel, train_id, &reply);
388}
389
391 ab_gp_train_session_t sessions[],
392 ab_gp_db_t *db, uint8_t train_id,
393 const uint8_t *payload, size_t payload_len,
394 uint32_t cycle, uint32_t timestamp_ms)
395{
398 ab_gp_train_session_t *session = NULL;
399
400 /* REQ-RBC-005: the wire-supplied train_id is range-checked before it indexes sessions[] or the ERTMS context.
401 * The plain-ERTMS caller (pre_execute.c) logs the false return; on the SaF path an out-of-range id never gets
402 * here, ab_gp_saf_train_on_frame() rejects it first and that rejection is logged. */
403 if ((payload == NULL) || (train_id < 1U) || (train_id > (uint8_t)RTE_EXAMPLE_MAX_TRAINS))
404 {
405 return false;
406 }
407
408 if (!rbc_train_codec_decode_train_to_track(payload, payload_len, &inbound))
409 {
410 return false;
411 }
412
414 if (ctx == NULL)
415 {
416 return false;
417 }
419
420 if (sessions != NULL)
421 {
422 session = &sessions[train_id - 1U];
423 }
424
425 switch (inbound.nid_message)
426 {
428 handle_msg_155(channel, session, db, train_id, ctx, &inbound.payload.msg_155, cycle, timestamp_ms);
429 return true;
430
432 handle_msg_129(&inbound.payload.msg_129, ctx, train_id, timestamp_ms);
433 return true;
434
436 handle_msg_136(channel, session, db, train_id, ctx, &inbound.payload.msg_136, cycle, timestamp_ms);
437 /* Raise the semantic event too - reaches the (stub) position
438 * FSM. handle_msg_136() above still does the real work. */
440 return true;
441
443 handle_msg_132(channel, session, db, train_id, ctx);
445 return true;
446
448 handle_msg_130(channel, train_id, ctx, &inbound.payload.msg_130, cycle, timestamp_ms);
449 return true;
450
452 /* Real Msg 146 acks by timestamp, not ma_seq (this codec's
453 * own rbc_msg_146_ack_t only carries t_train_ack) - this
454 * simplified flow has at most one outstanding MA per train,
455 * so acking the currently-active ma_seq is a safe, deliberate
456 * simplification, not a wire-format gap. */
457 (void)ab_gp_proc_ma_handle_ack(ctx, ctx->ma.ma_seq);
458 if (session != NULL)
459 {
460 session->ma_acked = true;
461 }
463 return true;
464
466 {
467 /* FR-RBC-EOM-003: releases every route this train holds and
468 * returns the session to IDLE - same teardown shape
469 * RBC_MSG_TRAIN_DISCONNECT's own handler already uses. */
470 bool db_removed = true;
471
474 if (db != NULL)
475 {
476 /* ab_gp_train_remove() itself refuses to remove a train
477 * still holding routes in db (route_count > 0) - see its
478 * own doc. If that ever happens, session->in_use must
479 * NOT be cleared below regardless: doing so unconditionally
480 * would leave sessions[] saying "not in use" while db
481 * still says "connected", the exact session/db drift
482 * this dispatcher's own session-sync exists to prevent
483 * (see ab_gp_proc_dispatch.h's own doc). Logged, not
484 * silently swallowed with (void), so a real occurrence is
485 * actually visible. */
486 db_removed = ab_gp_train_remove(db, train_id);
487 if (!db_removed)
488 {
490 "cycle %u: ERTMS EoM for train %u could not remove db train slot "
491 "(routes still held) - leaving session in_use to avoid session/db drift\n",
492 cycle, (unsigned int)train_id);
493 }
494 }
495 if ((session != NULL) && db_removed)
496 {
497 session->in_use = false;
498 }
499 return true;
500 }
501
503 (void)ab_gp_proc_session_handle_established(ctx, inbound.payload.msg_159.m_version, timestamp_ms);
504 return true;
505
506 default:
507 /* REQ-RBC-002: a decoded-but-unhandled nid_message is
508 * rejected here, not silently forwarded - the caller logs it. */
509 return false;
510 }
511}
ab_gp_saf_train_t * ab_gp_channel_saf_train(ab_gp_channel_handle_t handle)
This channel's train-link SaF termination (ab_gp_saf_train.h), or NULL for a NULL handle.
struct ab_gp_channel_context_s * ab_gp_channel_handle_t
Opaque handle over this component's own static per-process context.
rte_status_t ab_gp_channel_stage_relay(ab_gp_channel_handle_t handle, rte_example_relay_kind_t kind, uint8_t index, const uint8_t *bytes, size_t size)
Queues a relay-link send for this cycle - does not transmit yet.
Stage-then-commit output queue for this cycle's own DECISION output (ADR-034): the peer AB_SAMPLE and...
bool ab_gp_db_train_get_routes(const ab_gp_db_t *db, uint8_t train_id, uint16_t out_routes[RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN], uint8_t *out_count)
Retrieves routes currently allocated to a train.
Definition ab_gp_db.c:444
bool ab_gp_dispatch(ab_gp_ertms_train_context_t *ctx, ab_gp_event_t event)
Raises event to every state machine subscribed to it, in subscription-table order,...
Synchronous, statically-wired event dispatch for GP's per-entity procedure state machines (state_mach...
ab_gp_ertms_train_context_t * ab_gp_ertms_engine_get_train_context(uint8_t train_id)
Retrieves the ERTMS procedure context for a given train slot.
bool ab_gp_ertms_calc_ma_for_route(uint8_t train_id, uint16_t route_id, uint32_t ma_seq)
Computes a Movement Authority for a train on a given route.
bool ab_gp_ertms_update_train_position(uint8_t train_id, uint32_t nid_lrbg, uint32_t d_lrbg_m, rbc_q_dirlrbg_t q_dirlrbg, uint32_t v_train_kmh, uint32_t m_mode, uint32_t m_level, uint32_t cycle, uint32_t timestamp_ms)
Updates train position and evaluates segment/route occupancy.
bool ab_gp_ertms_validate_train_data(uint8_t train_id, uint32_t l_train_m, uint32_t v_maxtrain_kmh, uint8_t m_axleload, uint8_t m_loadinggauge, bool m_airtight, uint32_t timestamp_ms)
Validates train characteristics against site route topology.
bool ab_gp_ertms_extend_ma_for_route(uint8_t train_id, uint16_t route_id)
Extends an existing Movement Authority with an additional route.
Unified ERTMS Subset-026 Chapter 5 Operational Procedure Orchestrator.
bool rbc_train_codec_decode_train_to_track(const uint8_t *in_buffer, size_t buffer_size, rbc_train_inbound_msg_t *out_msg)
Decodes an inbound Train-to-Track message (Msg 129, 130, 132, 136, 146, 147, 150, 155,...
bool rbc_train_codec_encode_track_to_train(const rbc_train_outbound_msg_t *msg, uint8_t *out_buffer, size_t buffer_size, size_t *out_bytes_written)
Encodes an outbound Track-to-Train message (Msg 2, 3, 6, 8, 9, 15, 16, 18, 24, 33,...
#define RBC_MSG_TRAIN_TO_TRACK_POSITION_REPORT
#define RBC_MSG_TRAIN_TO_TRACK_INIT_SESSION
#define RBC_MSG_TRAIN_TO_TRACK_REQUEST_FOR_SHUNTING
#define RBC_MSG_TRAIN_TO_TRACK_END_OF_MISSION
#define RBC_MSG_TRAIN_TO_TRACK_VALIDATED_TRAIN_DATA
#define RBC_MSG_TRACK_TO_TRAIN_MOVEMENT_AUTHORITY
#define RBC_MSG_TRACK_TO_TRAIN_GENERAL_MESSAGE
#define RBC_MSG_TRAIN_TO_TRACK_ACK_EMERGENCY_STOP
#define RBC_MSG_TRAIN_TO_TRACK_MA_REQUEST
#define RBC_MSG_TRAIN_TO_TRACK_TERMINATE_SESSION
#define RBC_MSG_TRAIN_TO_TRACK_ACKNOWLEDGEMENT
#define RBC_MSG_TRAIN_TO_TRACK_SESSION_ESTABLISHED
@ AB_GP_EVENT_MA_REQUESTED
Definition ab_gp_event.h:85
@ AB_GP_EVENT_MA_ACKNOWLEDGED
Definition ab_gp_event.h:86
@ AB_GP_EVENT_POSITION_REPORTED
Definition ab_gp_event.h:89
@ AB_GP_EVENT_END_OF_MISSION
Definition ab_gp_event.h:92
static void handle_msg_129(const rbc_msg_129_validated_train_data_t *m129, ab_gp_ertms_train_context_t *ctx, uint8_t train_id, uint32_t timestamp_ms)
static rbc_timestamp_ms_t inbound_t_train(const rbc_train_inbound_msg_t *in)
static void build_config_msg_24(rbc_msg_24_general_message_t *m24, rbc_nid_engine_t nid_engine)
The one-time (per session) Msg 24 reply to Msg 155/136's own "confirm train data, inject config" step...
static rbc_timestamp_ms_t s_reply_t_train
static void handle_msg_155(ab_gp_channel_handle_t channel, ab_gp_train_session_t *session, ab_gp_db_t *db, uint8_t train_id, ab_gp_ertms_train_context_t *ctx, const rbc_msg_155_init_session_t *m155, uint32_t cycle, uint32_t timestamp_ms)
static void handle_msg_132(ab_gp_channel_handle_t channel, ab_gp_train_session_t *session, ab_gp_db_t *db, uint8_t train_id, ab_gp_ertms_train_context_t *ctx)
static void handle_msg_136(ab_gp_channel_handle_t channel, ab_gp_train_session_t *session, ab_gp_db_t *db, uint8_t train_id, ab_gp_ertms_train_context_t *ctx, const rbc_msg_136_position_report_t *m136, uint32_t cycle, uint32_t timestamp_ms)
static void handle_msg_130(ab_gp_channel_handle_t channel, uint8_t train_id, ab_gp_ertms_train_context_t *ctx, const rbc_msg_130_request_for_shunting_t *m130, uint32_t cycle, uint32_t timestamp_ms)
Msg 130 Request for Shunting (Subset-026 5.6): position update, decision (ab_gp_proc_shunting_handle_...
static bool build_and_stage_reply(ab_gp_channel_handle_t channel, uint8_t train_id, const rbc_train_outbound_msg_t *out_msg)
Builds the RBC_MSG_ERTMS_ENVELOPE wire frame (2-byte kind+train_id prefix + the codec's own encoded b...
bool ab_gp_proc_dispatch_train_inbound(ab_gp_channel_handle_t channel, ab_gp_train_session_t sessions[], ab_gp_db_t *db, uint8_t train_id, const uint8_t *payload, size_t payload_len, uint32_t cycle, uint32_t timestamp_ms)
Decodes one RBC_MSG_ERTMS_ENVELOPE payload and dispatches it into the ertms_procedures/ engine,...
Glue between RBC_MSG_ERTMS_ENVELOPE wire frames and the real Subset-026 procedure engine (ab_gp_ertms...
bool ab_gp_proc_ma_handle_ack(ab_gp_ertms_train_context_t *ctx, uint32_t ma_seq)
Handles Movement Authority Acknowledgement (Msg 146).
bool ab_gp_proc_session_handle_initiation(ab_gp_ertms_train_context_t *ctx, uint32_t cycle, uint32_t timestamp_ms)
Handles session initiation request (Msg 155 / P0).
bool ab_gp_proc_session_handle_termination(ab_gp_ertms_train_context_t *ctx, ab_gp_db_t *db)
Handles session termination (Msg 156 / Msg 41).
bool ab_gp_proc_session_handle_established(ab_gp_ertms_train_context_t *ctx, uint8_t m_version, uint32_t timestamp_ms)
Handles session established confirmation (Msg 159).
const char * ab_gp_proc_shunting_decision_name(ab_gp_shunting_decision_t decision)
bool ab_gp_proc_shunting_build_reply(ab_gp_shunting_decision_t decision, rbc_timestamp_ms_t t_train_reply, rbc_timestamp_ms_t t_train_request, rbc_nid_lrbg_t nid_lrbg, rbc_train_outbound_msg_t *out)
Builds the answer to a Msg 130: Msg 28 SH Authorised or Msg 27 SH Refused.
ab_gp_shunting_decision_t ab_gp_proc_shunting_handle_request(ab_gp_ertms_train_context_t *ctx, uint8_t train_id, uint32_t v_train_kmh)
Decides one Msg 130 Request for Shunting and applies the outcome.
ab_gp_shunting_decision_t
bool ab_gp_saf_envelope_encode(uint8_t train_id, const uint8_t *frame, size_t frame_len, uint8_t out[RBC_TRAIN_ENVELOPE_WIRE_SIZE])
Builds an RBC_MSG_SAF_ENVELOPE relay frame (RBC_TRAIN_ENVELOPE_WIRE_SIZE bytes).
bool ab_gp_saf_train_wrap(ab_gp_saf_train_t *s, uint8_t train_id, const uint8_t *pdu, size_t pdu_len, uint8_t *out_frame, size_t out_cap, size_t *out_len)
Protects one outbound application PDU for train slot train_id (only in DATA).
Train link safe communication (Subset-037 SaF) terminated inside A and B - REQ-SC-001,...
#define AB_GP_SAF_FRAME_MAX
Largest SaF frame one Train relay envelope carries.
bool ab_gp_train_handle_connect(ab_gp_db_t *db, uint8_t train_id)
Handles an inbound P0 (connect handshake) - wraps ab_gp_train_add() with the same env->train_id-as-ni...
bool ab_gp_train_remove(ab_gp_db_t *db, uint8_t train_id)
Removes a train on disconnect: resets db->trains[train_id-1] back to its all-zero/disconnected state.
bool ab_gp_train_handle_position_report(ab_gp_db_t *db, uint8_t train_id, uint32_t nid_lrbg)
Handles an inbound M136 (Position Report) - adds the train first (ab_gp_train_handle_connect()) if th...
#define RTE_EXAMPLE_LOG(...)
#define RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN
#define RBC_TRAIN_ENVELOPE_WIRE_SIZE
#define RTE_EXAMPLE_MAX_TRAINS
@ RBC_M_ACK_NOT_REQUIRED
@ RBC_M_ACK_REQUIRED
uint64_t rbc_timestamp_ms_t
Timestamp in milliseconds (POSIX or ETCS T_TRAIN / T_RBC scale).
uint32_t rbc_nid_engine_t
ETCS On-board Engine Identifier / Train ID (24 bits in ETCS).
@ AB_GP_ERTMS_SESSION_IDLE
@ AB_GP_TRAIN_DATA_NONE
The RBC Train/IL/CTC scenario's shared wire envelope (ADR-029) - one fixed-size struct/frame reused f...
@ RBC_MSG_ERTMS_ENVELOPE
West/East site identity and the per-site config derived from it (ports, container host lookup) - see ...
@ RTE_EXAMPLE_RELAY_KIND_TRAIN
Definition site_config.h:40
rbc_packet_21_gradient_profile_t p21
uint16_t route_ids[RTE_EXAMPLE_MAX_ROUTES_PER_TRAIN]
rbc_packet_5_linking_t p5
rbc_packet_27_ssp_t p27
Complete ERTMS state and procedure context for one train slot.
ab_gp_ertms_session_state_t session_state
ab_gp_ertms_train_data_t train_data
ab_gp_ertms_ma_record_t ma
ab_gp_train_data_state_t state
One channel's train-link SaF termination.
Msg 130: Request for Shunting (Subset-026 8.6.2) - header plus a position report, same bare (no leadi...
rbc_packet_0_position_report_t position_report
Msg 136: Train Position Report - carries Packet 0 OR Packet 1 (Subset-026 8.6.4: "Packet 0 or 1"),...
rbc_packet_0_position_report_t position_report
Msg 155: Initiation of a Communication Session.
rbc_train_to_track_header_t header
Msg 24: General Message (National Values, TSRs, Text, Parameters).
rbc_packet_3_national_values_t national_values
rbc_packet_57_ma_request_params_t ma_request_params
rbc_nid_bg_t nid_bg
union rbc_train_inbound_msg_t::@156151041174124231025067150227167311270040326010 payload
union rbc_train_outbound_msg_t::@072257326371153356142277360163235337000010176256 payload