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
channel_callbacks_example.c
Go to the documentation of this file.
1
14
15#include <stdint.h>
16#include <stdbool.h>
17#include <string.h>
18#include <stdio.h>
19#include <stdlib.h>
20
21#include "rte/status/rte_status.h"
22
23/* ============================================================================
24 * Channel Callback Definition
25 * ========================================================================== */
26
38typedef void (*rte_channel_callback_t)(const char *channel_name,
39 const void *data,
40 size_t data_size,
41 void *context);
42
43/* ============================================================================
44 * Application Context and Data Types
45 * ========================================================================== */
46
47typedef struct {
48 uint32_t command_id;
49 uint32_t speed_kmh;
50 uint8_t emergency_stop;
52
53typedef struct {
54 uint32_t status_code;
55 bool is_healthy;
56 uint32_t error_count;
58
59typedef struct {
60 // Channel metrics
61 uint32_t vital_commands_received;
62 uint32_t feedback_messages_received;
63 uint32_t telemetry_messages_received;
64 uint32_t config_updates_applied;
65
66 // State
67 train_command_t last_command;
68 standby_status_t standby_status;
69 bool running;
71
72/* ============================================================================
73 * Channel Registry (for managing named channels)
74 * ========================================================================== */
75
76#define MAX_CHANNELS 16
77
78typedef struct {
79 const char *name;
81 void *context;
82 // In real implementation: rte_ipc_handle_t handle;
84
85typedef struct {
86 channel_registry_entry_t channels[MAX_CHANNELS];
87 uint32_t count;
89
90static channel_registry_t g_channel_registry = {0};
91
97 void *context)
98{
99 if (g_channel_registry.count >= MAX_CHANNELS) {
101 }
102
103 channel_registry_entry_t *entry = &g_channel_registry.channels[g_channel_registry.count];
104 entry->name = name;
105 entry->callback = callback;
106 entry->context = context;
107
108 g_channel_registry.count++;
109 printf("✓ Registered channel: %s\n", name);
110 return RTE_STATUS_OK;
111}
112
117{
118 for (uint32_t i = 0; i < g_channel_registry.count; i++) {
119 if (strcmp(g_channel_registry.channels[i].name, name) == 0) {
120 return &g_channel_registry.channels[i];
121 }
122 }
123 return NULL;
124}
125
126/* ============================================================================
127 * Callback Implementations (User provides these)
128 * ========================================================================== */
129
137void on_vital_command_received(const char *channel_name,
138 const void *data,
139 size_t data_size,
140 void *context)
141{
142 app_context_t *app = (app_context_t *)context;
143
144 printf("\n[CALLBACK] Channel: %s\n", channel_name);
145 printf(" Data size: %zu bytes\n", data_size);
146
147 // Validate
148 if (data_size != sizeof(train_command_t)) {
149 printf("✗ ERROR: Invalid command size on %s\n", channel_name);
150 return;
151 }
152
153 // Parse
154 const train_command_t *cmd = (const train_command_t *)data;
155 printf(" Command ID: %u\n", cmd->command_id);
156 printf(" Speed: %u km/h\n", cmd->speed_kmh);
157 printf(" E-Stop: %s\n", cmd->emergency_stop ? "YES" : "NO");
158
159 // Process
160 app->last_command = *cmd;
161 app->vital_commands_received++;
162
163 // Log for debugging/monitoring
164 printf("✓ Vital command processed (total received: %u)\n",
165 app->vital_commands_received);
166}
167
174void on_standby_feedback_received(const char *channel_name,
175 const void *data,
176 size_t data_size,
177 void *context)
178{
179 app_context_t *app = (app_context_t *)context;
180
181 printf("\n[CALLBACK] Channel: %s\n", channel_name);
182 printf(" Data size: %zu bytes\n", data_size);
183
184 if (data_size != sizeof(standby_status_t)) {
185 printf("✗ ERROR: Invalid status size on %s\n", channel_name);
186 return;
187 }
188
189 const standby_status_t *status = (const standby_status_t *)data;
190 printf(" Status code: %u\n", status->status_code);
191 printf(" Healthy: %s\n", status->is_healthy ? "YES" : "NO");
192 printf(" Error count: %u\n", status->error_count);
193
194 // Update state
195 app->standby_status = *status;
196 app->feedback_messages_received++;
197
198 // Health check
199 if (!status->is_healthy) {
200 printf("⚠️ WARNING: Standby unhealthy on %s\n", channel_name);
201 }
202
203 if (status->error_count > 10) {
204 printf("⚠️ WARNING: High error count on %s\n", channel_name);
205 }
206
207 printf("✓ Feedback processed (total received: %u)\n",
208 app->feedback_messages_received);
209}
210
217void on_telemetry_received(const char *channel_name,
218 const void *data,
219 size_t data_size,
220 void *context)
221{
222 app_context_t *app = (app_context_t *)context;
223
224 printf("\n[CALLBACK] Channel: %s\n", channel_name);
225 printf(" Telemetry size: %zu bytes\n", data_size);
226
227 // Non-vital: just log and continue
228 app->telemetry_messages_received++;
229 printf("✓ Telemetry logged (total received: %u)\n",
230 app->telemetry_messages_received);
231}
232
239void on_config_update_received(const char *channel_name,
240 const void *data,
241 size_t data_size,
242 void *context)
243{
244 app_context_t *app = (app_context_t *)context;
245
246 printf("\n[CALLBACK] Channel: %s\n", channel_name);
247 printf(" Config size: %zu bytes\n", data_size);
248
249 // Validate
250 if (data_size < 4) {
251 printf("✗ ERROR: Invalid config on %s\n", channel_name);
252 return;
253 }
254
255 // Would apply configuration here
256 app->config_updates_applied++;
257 printf("✓ Configuration applied from %s (total: %u)\n",
258 channel_name, app->config_updates_applied);
259}
260
261/* ============================================================================
262 * Simulated Event Loop
263 * ========================================================================== */
264
271void simulate_channel_data(const char *channel_name,
272 const void *data,
273 size_t size)
274{
275 printf("\n=== DATA ARRIVING ON CHANNEL ===\n");
276
277 // Look up channel in registry
279 if (!ch) {
280 printf("✗ Channel not found: %s\n", channel_name);
281 return;
282 }
283
284 // Invoke callback (this is what OS OSAdapter does)
285 if (ch->callback) {
286 ch->callback(channel_name, data, size, ch->context);
287 }
288}
289
290/* ============================================================================
291 * Application Example
292 * ========================================================================== */
293
294int main(void)
295{
296 printf("========================================\n");
297 printf("Channel Callbacks Example\n");
298 printf("========================================\n");
299
300 // Initialize app context
301 app_context_t app = {
302 .vital_commands_received = 0,
303 .feedback_messages_received = 0,
304 .telemetry_messages_received = 0,
305 .config_updates_applied = 0,
306 .running = true,
307 };
308
309 /* ====================================================================
310 * STEP 1: Register named channels with callbacks at startup
311 * ==================================================================== */
312
313 printf("\n--- STEP 1: Register Named Channels ---\n");
314
315 // Vital command channel
317 "online_to_standby_vital",
319 &app
320 );
321
322 // Feedback channel
324 "standby_to_online_feedback",
326 &app
327 );
328
329 // Telemetry channel
331 "online_to_diag_telemetry",
333 &app
334 );
335
336 // Configuration channel
338 "config_update_channel",
340 &app
341 );
342
343 printf("\nAll channels registered. Waiting for events...\n");
344
345 /* ====================================================================
346 * STEP 2: Simulate events (in real system, OS OSAdapter triggers these)
347 * ==================================================================== */
348
349 printf("\n--- STEP 2: Simulate Channel Events ---\n");
350
351 // Event 1: Vital command arrives
352 train_command_t cmd = {
353 .command_id = 1001,
354 .speed_kmh = 80,
355 .emergency_stop = 0,
356 };
357 simulate_channel_data("online_to_standby_vital", &cmd, sizeof(cmd));
358
359 // Event 2: Standby feedback arrives
360 standby_status_t status = {
361 .status_code = 0,
362 .is_healthy = true,
363 .error_count = 0,
364 };
365 simulate_channel_data("standby_to_online_feedback", &status, sizeof(status));
366
367 // Event 3: Telemetry arrives
368 uint8_t telemetry_data[100] = {0x42, 0x43};
369 simulate_channel_data("online_to_diag_telemetry", telemetry_data, sizeof(telemetry_data));
370
371 // Event 4: Another vital command
372 cmd.command_id = 1002;
373 cmd.speed_kmh = 100;
374 simulate_channel_data("online_to_standby_vital", &cmd, sizeof(cmd));
375
376 // Event 5: Configuration update
377 uint8_t config_data[32] = {0xAA, 0xBB};
378 simulate_channel_data("config_update_channel", config_data, sizeof(config_data));
379
380 // Event 6: Standby degradation
381 status.is_healthy = false;
382 status.error_count = 15;
383 simulate_channel_data("standby_to_online_feedback", &status, sizeof(status));
384
385 /* ====================================================================
386 * STEP 3: Report metrics
387 * ==================================================================== */
388
389 printf("\n--- STEP 3: Metrics Summary ---\n");
390 printf("Vital commands received: %u\n", app.vital_commands_received);
391 printf("Feedback messages received: %u\n", app.feedback_messages_received);
392 printf("Telemetry messages received: %u\n", app.telemetry_messages_received);
393 printf("Config updates applied: %u\n", app.config_updates_applied);
394
395 printf("\nLast command: ID=%u, Speed=%u km/h, E-Stop=%s\n",
396 app.last_command.command_id,
397 app.last_command.speed_kmh,
398 app.last_command.emergency_stop ? "YES" : "NO");
399
400 printf("Standby status: Healthy=%s, Errors=%u\n",
401 app.standby_status.is_healthy ? "YES" : "NO",
402 app.standby_status.error_count);
403
404 printf("\n========================================\n");
405 printf("Key Takeaways\n");
406 printf("========================================\n");
407 printf("✓ Each channel has a unique name\n");
408 printf("✓ Callbacks are registered at startup\n");
409 printf("✓ OS osadapter calls callback when data arrives\n");
410 printf("✓ Callback identifies channel by name\n");
411 printf("✓ No polling needed (event-driven)\n");
412 printf("✓ Easy to add/remove channels\n");
413 printf("✓ Easy to log and monitor by channel name\n");
414
415 return 0;
416}
void on_telemetry_received(const char *channel_name, const void *data, size_t data_size, void *context)
Callback: Telemetry received.
rte_status_t channel_registry_register(const char *name, rte_channel_callback_t callback, void *context)
Register a named channel with callback.
void on_standby_feedback_received(const char *channel_name, const void *data, size_t data_size, void *context)
Callback: Standby feedback/health received.
void simulate_channel_data(const char *channel_name, const void *data, size_t size)
Simulate data arriving on a channel.
channel_registry_entry_t * channel_registry_find(const char *name)
Find channel by name.
void on_vital_command_received(const char *channel_name, const void *data, size_t data_size, void *context)
Callback: Vital command received on channel.
void on_config_update_received(const char *channel_name, const void *data, size_t data_size, void *context)
Callback: Configuration update received.
void(*) rte_channel_callback_t(const char *channel_name, const void *data, size_t data_size, void *context)
Callback invoked when data is available on a channel.
rte_status_t
Common result/status codes.
Definition rte_status.h:27
@ RTE_STATUS_OK
Definition rte_status.h:28
@ RTE_STATUS_RESOURCE_EXHAUSTED
Definition rte_status.h:33