RTE RBC 2oo2 Generic Application 0.1.0 build 308eda7
IL/CTC route and train logic for the RBC_GP reference RBC
Loading...
Searching...
No Matches
ab_ga_ma_logic_adaptation.c
Go to the documentation of this file.
1
7
8#include "rte/oal/log/rte_log.h"
9
10#include "common_config.h" /* RTE_EXAMPLE_LOG - this module's own setup-failure log, see
11 * ab_ga_ma_adaptation_init()'s own doc, ga_interface.h */
12#include "ab_siteGA.h" /* ab_site_ga_route_layout_t - GA's own reduced site header, implemented by
13 * safeAPIRBC2oo2SA (sa::site::ga), same direct-include posture as every
14 * other GA module (ga_interface.h's own doc) */
15#include "../main/ab_ga_dispatch.h" /* ab_ga_dispatch_init() - GA's single GP-notification
16 * subscriber, see that file's own doc */
17#include "../il/ab_ga_il.h" /* ab_ga_il_site_has_route()/_route_exists() - used by
18 * this file's own validate_route_assignment() below */
19
21
24typedef struct
25{
26 const ab_gp_train_session_t *sessions;
27 const ab_gp_db_t *db;
29
31/* One GA instance per process/channel, set once by ab_ga_ma_adaptation_init() during setup. */
33
35const char *g_ga_role_tag = "";
36
38static bool train_holds_preceding_route(const ab_gp_db_t *db, const ab_site_ga_route_layout_t *layout, uint8_t train_id);
39static bool validate_route_assignment(void *context, uint16_t route_id, uint8_t train_id);
40static bool validate_shunting_request(void *context, uint8_t train_id);
41
42
44rte_status_t ab_ga_ma_adaptation_init(ab_gp_train_session_t *sessions, ab_gp_db_t *db, rte_example_site_t site,
45 const char *role_tag)
46{
47 rte_status_t status;
48
49 g_ga_role_tag = role_tag;
50
51 status = ab_gp_ga_register_init(validate_route_assignment, (void *)db);
52 if (status == RTE_STATUS_OK)
53 {
54 g_shunting_context.sessions = sessions;
55 g_shunting_context.db = db;
56 status = ab_gp_ga_register_shunting_validator(validate_shunting_request, (void *)&g_shunting_context);
57 }
58 if (status == RTE_STATUS_OK)
59 {
60 /* GA's single dispatch module (ab_ga_dispatch.c) - the only
61 * thing that registers a route-context/train-context/IL-envelope/
62 * IL-CTC-output-producer subscription with GP now, fanning out to
63 * il/ctc internally. Replaces the old
64 * ab_ga_il_init(role_tag)/ab_ga_ctc_init(role_tag) pair
65 * (interface-simplification pass). */
66 status = ab_ga_dispatch_init(sessions, db);
67 }
68 if (status != RTE_STATUS_OK)
69 {
70 RTE_EXAMPLE_LOG("[%s] GA registration -> %s\n", role_tag, rte_status_to_string(status));
71 rte_log_write_event(RTE_LOG_LEVEL_ERROR, site_config_name(site), 0U, role_tag, "-", "GA",
72 "GA registration failed", NULL);
73 }
74 return status;
75}
76
77
78/****Local functions ****/
79
83static bool train_holds_preceding_route(const ab_gp_db_t *db, const ab_site_ga_route_layout_t *layout, uint8_t train_id)
84{
85 ab_gp_route_context_t prev_ctx;
86 size_t i;
87
88 /* 1. Direct predecessor by prev_route_id */
89 if (layout->prev_route_id != 0U)
90 {
91 if (ab_gp_db_get_route_context(db, layout->prev_route_id, &prev_ctx))
92 {
93 if (prev_ctx.used_in_ma && (prev_ctx.train_id == train_id))
94 {
95 return true;
96 }
97 }
98 }
99
100 /* 2. Any route ending at candidate route's start signal held by this train */
101 for (i = 0U; i < ab_site_ga_track_layout_count; i++)
102 {
103 if (ab_site_ga_track_layout[i].end_signal == layout->start_signal)
104 {
105 if (ab_gp_db_get_route_context(db, ab_site_ga_track_layout[i].id, &prev_ctx))
106 {
107 if (prev_ctx.used_in_ma && (prev_ctx.train_id == train_id))
108 {
109 return true;
110 }
111 }
112 }
113 }
114
115 return false;
116}
117
129static bool validate_route_assignment(void *context, uint16_t route_id, uint8_t train_id)
130{
131 const ab_gp_db_t *db = (const ab_gp_db_t *)context;
132 const ab_site_ga_route_layout_t *layout = NULL;
133 uint32_t last_nid_lrbg = 0U;
134 bool balise_found = false;
135 uint8_t b;
136
137 if (!ab_ga_il_site_has_route(route_id, &layout))
138 {
139 return false; /* not a route this site's own layout knows about */
140 }
141 if (!ab_gp_db_route_exists(db, route_id))
142 {
143 return false; /* route not set/locked by Interlocking in DB */
144 }
145 /* If train has a last position inside the route then allow to send MA */
146 if (ab_gp_train_get_last_position(db, train_id, &last_nid_lrbg) && (last_nid_lrbg != 0U))
147 {
148 if (layout->balise_count == 0U)
149 {
150 return true;
151 }
152 for (b = 0U; b < layout->balise_count; b++)
153 {
154 if (layout->balise_nid_lrbgs[b] == last_nid_lrbg)
155 {
156 rte_log_write_event(RTE_LOG_LEVEL_INFO, g_ga_role_tag,
157 0U, "GA", "GP", "ROUTE_VALIDATION",
158 "train's last position matches route balise", NULL);
159 balise_found = true;
160 break;
161 }
162 }
163 if (!balise_found)
164 {
165 if (train_holds_preceding_route(db, layout, train_id))
166 {
167 rte_log_write_event(RTE_LOG_LEVEL_INFO, g_ga_role_tag,
168 0U, "GA", "GP", "ROUTE_VALIDATION",
169 "route is extension of route held by train", NULL);
170 return true;
171 }
172
173 rte_log_write_event(RTE_LOG_LEVEL_WARNING, g_ga_role_tag,
174 0U, "GA", "GP", "ROUTE_VALIDATION",
175 "train's last position does NOT match any route balise and not an extension", NULL);
176 return false; /* reported balise does not match this route */
177 }
178 }
179
180 return true;
181}
182
187static bool validate_shunting_request(void *context, uint8_t train_id)
188{
189 const ab_ga_shunting_context_t *sc = (const ab_ga_shunting_context_t *)context;
190 ab_gp_train_context_t train_ctx;
191
192 if ((sc == NULL) || (sc->sessions == NULL) || (sc->db == NULL)
193 || !ab_gp_get_train_context(sc->sessions, sc->db, train_id, &train_ctx))
194 {
195 return false;
196 }
197 if ((train_ctx.route_count > 0U) || train_ctx.has_ma)
198 {
199 rte_log_write_event(RTE_LOG_LEVEL_INFO, g_ga_role_tag, 0U, "GA", "GP", "SHUNTING_VALIDATION",
200 "SH refused: train holds a route or an active MA", NULL);
201 return false;
202 }
203 return true;
204}
rte_status_t ab_ga_dispatch_init(ab_gp_train_session_t *sessions, ab_gp_db_t *db)
Registers every GA<->GP subscription this process needs, in one place: route-context notify,...
GA's single GP-notification subscriber AND registration point for everything GP calls into GA with - ...
char * g_ga_role_tag
bool ab_ga_il_site_has_route(uint16_t route_id, const ab_site_ga_route_layout_t **out_layout)
Pure site-layout lookup - does route_id exist in this site's own static track layout at all (ab_site_...
Definition ab_ga_il.c:71
A/B's own route handling against GP's own runtime table (via AB/GP/ga_interface/ga_interface....
static bool validate_shunting_request(void *context, uint8_t train_id)
static bool validate_route_assignment(void *context, uint16_t route_id, uint8_t train_id)
static bool train_holds_preceding_route(const ab_gp_db_t *db, const ab_site_ga_route_layout_t *layout, uint8_t train_id)
Checks if the given train already holds a preceding route connecting to layout.
static ab_ga_shunting_context_t g_shunting_context
rte_status_t ab_ga_ma_adaptation_init(ab_gp_train_session_t *sessions, ab_gp_db_t *db, rte_example_site_t site, const char *role_tag)
GA's own single entry point, IMPLEMENTED here - ab_ga_ma_adaptation_init() is DECLARED in AB/GP/ga_in...
GA's own site data: route composition, built from GP's raw physical elements (railML interlocking <ro...
const ab_site_ga_route_layout_t ab_site_ga_track_layout[]
One route's static layout entry (railML interlocking <route>) - GA's own full definition (not a reduc...
Definition ab_siteGA.h:69
uint32_t balise_nid_lrbgs[RTE_EXAMPLE_MAX_BALISES_PER_ROUTE]
Definition ab_siteGA.h:86