Safe API Framework 0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <unistd.h>
31#include <signal.h>
32
33#include "rte/status/rte_status.h"
34#include "rte/types/rte_types.h"
35#include "rte/buffer/rte_buffer.h"
36#include "rte/string/rte_string.h"
37#include "rte/log/rte_log.h"
38#include "rte/timer/rte_timer.h"
39#include "rte/safestate/rte_safestate.h"
40
41/* ============================================================================
42 * Application Configuration
43 * ========================================================================== */
44
45#define APP_NAME "railway-message-processor"
46#define APP_VERSION "1.0.0"
47#define MESSAGE_BUFFER_SIZE 256U
48#define LOG_LINE_MAX 128U
49
50/* Application state machine */
51typedef enum {
52 STATE_INIT,
53 STATE_RUNNING,
54 STATE_ERROR,
55 STATE_SHUTDOWN
56} app_state_t;
57
58typedef struct {
59 app_state_t state;
60 uint32_t message_count;
61 uint32_t heartbeat_count;
62 uint32_t error_count;
63 volatile int running;
65
66static app_context_t g_app = {
67 .state = STATE_INIT,
68 .message_count = 0,
69 .heartbeat_count = 0,
70 .error_count = 0,
71 .running = 1
72};
73
74/* ============================================================================
75 * Helper Functions
76 * ========================================================================== */
77
88static void log_line(rte_log_level_t level, const char *line)
89{
90 rte_log_write(level, APP_NAME, line);
91}
92
97{
98 char line[LOG_LINE_MAX];
99 rte_status_t status = rte_log_init();
100 if (status != RTE_STATUS_OK) {
101 (void)fprintf(stderr, "Failed to initialize logging: %d\n", (int)status);
102 return status;
103 }
104
105 (void)snprintf(line, sizeof(line), "Initializing %s v%s", APP_NAME, APP_VERSION);
107 g_app.state = STATE_RUNNING;
108 log_line(RTE_LOG_LEVEL_INFO, "Application initialized successfully");
109 return RTE_STATUS_OK;
110}
111
117static rte_status_t process_message(const uint8_t *msg, size_t len)
118{
119 char line[LOG_LINE_MAX];
120 uint8_t msg_type;
121
122 RTE_ASSERT(msg != NULL);
123 RTE_ASSERT(len > 0U);
124 RTE_ASSERT(len <= MESSAGE_BUFFER_SIZE);
125
126 (void)snprintf(line, sizeof(line), "Processing message [%zu bytes]", len);
128
129 /* Example: Parse first byte as message type */
130 msg_type = msg[0];
131
132 switch (msg_type) {
133 case 0x01: /* HEARTBEAT */
134 log_line(RTE_LOG_LEVEL_INFO, "Received HEARTBEAT from train");
135 break;
136
137 case 0x02: /* POSITION_UPDATE */
138 if (len >= 5U) {
139 uint32_t position;
140 (void)memcpy(&position, &msg[1], sizeof(position));
141 (void)snprintf(line, sizeof(line), "Train position update: %u", position);
143 } else {
144 (void)snprintf(line, sizeof(line), "Invalid POSITION_UPDATE message (len=%zu)", len);
147 }
148 break;
149
150 case 0x03: /* COMMAND_ACK */
151 log_line(RTE_LOG_LEVEL_INFO, "Received command acknowledgment");
152 break;
153
154 default:
155 (void)snprintf(line, sizeof(line), "Unknown message type: 0x%02x", msg_type);
158 }
159
160 g_app.message_count++;
161 return RTE_STATUS_OK;
162}
163
170static void heartbeat_callback(rte_timer_handle_t handle, void *user_context)
171{
172 (void)handle;
173 (void)user_context;
174
175 g_app.heartbeat_count++;
176
177 /* Log heartbeat every 5th beat (reduce log spam) */
178 if ((g_app.heartbeat_count % 5U) == 0U) {
179 char line[LOG_LINE_MAX];
180 (void)snprintf(line, sizeof(line),
181 "Heartbeat #%u - Messages processed: %u, Errors: %u",
182 g_app.heartbeat_count,
183 g_app.message_count,
184 g_app.error_count);
186 }
187}
188
193{
194 /* Simulate different message types in sequence */
195 static const uint8_t sequence[] = {0x01, 0x02, 0x01, 0x03};
196 static size_t seq_idx = 0;
197
198 uint8_t message[MESSAGE_BUFFER_SIZE];
199 size_t msg_len;
200
201 message[0] = sequence[seq_idx % 4U];
202
203 /* Add position data for POSITION_UPDATE messages */
204 if (message[0] == 0x02U) {
205 uint32_t position = 1000U + (g_app.message_count * 50U);
206 (void)memcpy(&message[1], &position, sizeof(position));
207 msg_len = 5U;
208 } else {
209 msg_len = 1U;
210 }
211
212 seq_idx++;
213 return process_message(message, msg_len);
214}
215
219static void signal_handler(int sig)
220{
221 if ((sig == SIGINT) || (sig == SIGTERM)) {
222 g_app.running = 0;
223 }
224}
225
229static rte_status_t transition_to_state(app_state_t new_state)
230{
231 static const char *const state_names[] = {
232 "INIT", "RUNNING", "ERROR", "SHUTDOWN"
233 };
234
235 if ((uint32_t)new_state >= 4U) {
237 }
238
239 if (g_app.state == new_state) {
240 return RTE_STATUS_OK; /* Already in this state */
241 }
242
243 {
244 char line[LOG_LINE_MAX];
245 (void)snprintf(line, sizeof(line), "State transition: %s -> %s",
246 state_names[g_app.state], state_names[new_state]);
248 }
249
250 g_app.state = new_state;
251 return RTE_STATUS_OK;
252}
253
254/* ============================================================================
255 * Main Application
256 * ========================================================================== */
257
258int main(int argc, char *argv[])
259{
260 rte_status_t status;
261 uint32_t loop_count;
262
263 (void)argc;
264 (void)argv;
265
266 /* Set up signal handlers */
267 (void)signal(SIGINT, signal_handler);
268 (void)signal(SIGTERM, signal_handler);
269
270 /* Initialize application */
271 status = app_init();
272 if (status != RTE_STATUS_OK) {
273 (void)fprintf(stderr, "Initialization failed\n");
274 return EXIT_FAILURE;
275 }
276
277 /* No real timer OSAdapter is registered in this minimal example - the
278 * heartbeat callback is invoked directly from the loop below every
279 * 10th iteration instead of through rte_timer_create()/_start(). A
280 * real integration would register an OSAdapter (ADR-005) and use the
281 * real timer API. */
282 log_line(RTE_LOG_LEVEL_INFO, "Starting message processing loop (Ctrl+C to exit)");
283
284 loop_count = 0U;
285 while ((g_app.running != 0) && (loop_count < 50U)) {
286 loop_count++;
287
288 /* Simulate receiving a message */
289 status = simulate_train_message();
290 if (status != RTE_STATUS_OK) {
291 char line[LOG_LINE_MAX];
292 g_app.error_count++;
293 (void)snprintf(line, sizeof(line), "Message processing failed: %d", (int)status);
295 }
296
297 /* Simulate timer callback every 10 iterations */
298 if ((loop_count % 10U) == 0U) {
299 heartbeat_callback(NULL, NULL);
300 }
301
302 /* Small delay to prevent busy-waiting */
303 (void)usleep(100000); /* 100ms */
304 }
305
306 /* Shutdown */
307 log_line(RTE_LOG_LEVEL_INFO, "Shutting down...");
308 (void)transition_to_state(STATE_SHUTDOWN);
309
310 /* Print summary */
311 (void)printf("\n");
312 (void)printf("===================================================================\n");
313 (void)printf("%s Summary\n", APP_NAME);
314 (void)printf("===================================================================\n");
315 (void)printf("Messages processed: %u\n", g_app.message_count);
316 (void)printf("Heartbeats sent: %u\n", g_app.heartbeat_count);
317 (void)printf("Errors encountered: %u\n", g_app.error_count);
318 (void)printf("Final state: SHUTDOWN\n");
319 (void)printf("===================================================================\n");
320 (void)printf("\n");
321
322 return EXIT_SUCCESS;
323}
rte_log_level_t
Log message severity, passed to rte_log_write().
Definition rte_log.h:34
rte_status_t rte_log_init(void)
Initializes the logging OSAdapter. Safe to call once at startup.
Definition rte_log.c:99
void rte_log_write(rte_log_level_t level, const char *tag, const char *message)
Emits one log message. Non-blocking; never fails the caller's control flow even if the message is dro...
Definition rte_log.c:108
@ RTE_LOG_LEVEL_DEBUG
Definition rte_log.h:35
@ RTE_LOG_LEVEL_INFO
Definition rte_log.h:36
@ RTE_LOG_LEVEL_WARNING
Definition rte_log.h:37
@ RTE_LOG_LEVEL_ERROR
Definition rte_log.h:38
#define RTE_ASSERT(cond)
Checked assertion. Always active in every build configuration, including production (ADR-004 section ...
rte_status_t
Common result/status codes.
Definition rte_status.h:27
@ RTE_STATUS_OK
Definition rte_status.h:28
@ RTE_STATUS_INVALID_PARAM
Definition rte_status.h:29
struct rte_timer_impl_s * rte_timer_handle_t
Definition rte_timer.h:31
static rte_status_t transition_to_state(app_state_t new_state)
Safe state transition.
Definition main.c:229
static void heartbeat_callback(rte_timer_handle_t handle, void *user_context)
Timer callback - generates periodic heartbeats.
Definition main.c:170
static rte_status_t app_init(void)
Initialize the application context.
Definition main.c:96
static rte_status_t process_message(const uint8_t *msg, size_t len)
Process a single message (simulated).
Definition main.c:117
static void log_line(rte_log_level_t level, const char *line)
Logs one already-formatted line at the given level.
Definition main.c:88
static void signal_handler(int sig)
Signal handler for graceful shutdown.
Definition main.c:219
static rte_status_t simulate_train_message(void)
Simulate receiving a message from train.
Definition main.c:192