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
ipc-pubsub-example.c
Go to the documentation of this file.
1
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27#include <pthread.h>
28
29#include "rte/status.h"
30#include "rte/log.h"
31#include "rte/ipc/rte_ipc_pubsub.h"
32
33/* ============================================================================
34 * Message Definitions
35 * ========================================================================== */
36
40typedef struct {
41 uint32_t track_id;
42 uint8_t occupancy;
43 uint32_t speed_limit;
44 char description[32];
46
47#define TRACK_EMPTY 0
48#define TRACK_OCCUPIED 1
49#define TRACK_UNKNOWN 2
50
51/* ============================================================================
52 * Track Database (Publisher)
53 * ========================================================================== */
54
58static void* track_publisher_thread(void *arg)
59{
61
62 printf("[Publisher] Track status publisher starting\n");
63
64 /* Simulate track status changes */
65 track_status_t statuses[] = {
66 {.track_id = 1, .occupancy = TRACK_EMPTY, .speed_limit = 100, .description = "Clear"},
67 {.track_id = 2, .occupancy = TRACK_OCCUPIED, .speed_limit = 40, .description = "Train present"},
68 {.track_id = 3, .occupancy = TRACK_EMPTY, .speed_limit = 80, .description = "Clear"},
69 {.track_id = 1, .occupancy = TRACK_OCCUPIED, .speed_limit = 50, .description = "Train arriving"},
70 {.track_id = 2, .occupancy = TRACK_EMPTY, .speed_limit = 100, .description = "Train left"},
71 };
72
73 for (int i = 0; i < 5; i++) {
74 sleep(1);
75
76 track_status_t *status = &statuses[i];
77
78 printf("[Publisher] Publishing track %u status: %s\n",
79 status->track_id, status->description);
80
81 rte_status_t result = rte_ipc_pubsub_publish(*topic, status, sizeof(*status));
82
83 if (result != RTE_STATUS_OK) {
84 RTE_LOG_ERROR("Publish failed: %d", result);
85 }
86 }
87
88 printf("[Publisher] Publisher done\n");
89 return NULL;
90}
91
92/* ============================================================================
93 * Subscribers (Consumers)
94 * ========================================================================== */
95
99static void* signal_manager_thread(void *arg)
100{
102
103 printf("[Signal Manager] Started\n");
104
105 for (int i = 0; i < 5; i++) {
106 track_status_t status = {0};
107
109 *subscriber,
110 &status, sizeof(status),
111 2000 /* 2 second timeout */
112 );
113
114 if (result == RTE_STATUS_OK) {
115 printf("[Signal Manager] Track %u: ", status.track_id);
116
117 if (status.occupancy == TRACK_OCCUPIED) {
118 printf("Setting signal to RED (stop)\n");
119 } else if (status.speed_limit >= 80) {
120 printf("Setting signal to GREEN (go)\n");
121 } else {
122 printf("Setting signal to YELLOW (caution)\n");
123 }
124 } else if (result == RTE_STATUS_TIMEOUT) {
125 printf("[Signal Manager] No update received (timeout)\n");
126 }
127 }
128
129 printf("[Signal Manager] Done\n");
130 return NULL;
131}
132
136static void* speed_manager_thread(void *arg)
137{
139
140 printf("[Speed Manager] Started\n");
141
142 for (int i = 0; i < 5; i++) {
143 track_status_t status = {0};
144
146 *subscriber,
147 &status, sizeof(status),
148 2000
149 );
150
151 if (result == RTE_STATUS_OK) {
152 printf("[Speed Manager] Track %u: Speed limit = %u km/h\n",
153 status.track_id, status.speed_limit);
154 } else if (result == RTE_STATUS_TIMEOUT) {
155 printf("[Speed Manager] No update received (timeout)\n");
156 }
157 }
158
159 printf("[Speed Manager] Done\n");
160 return NULL;
161}
162
166static void* route_manager_thread(void *arg)
167{
169
170 printf("[Route Manager] Started\n");
171
172 for (int i = 0; i < 5; i++) {
173 track_status_t status = {0};
174
176 *subscriber,
177 &status, sizeof(status),
178 2000
179 );
180
181 if (result == RTE_STATUS_OK) {
182 if (status.occupancy == TRACK_OCCUPIED) {
183 printf("[Route Manager] Track %u occupied - rerouting trains\n",
184 status.track_id);
185 } else {
186 printf("[Route Manager] Track %u available - planning route\n",
187 status.track_id);
188 }
189 } else if (result == RTE_STATUS_TIMEOUT) {
190 printf("[Route Manager] No update received (timeout)\n");
191 }
192 }
193
194 printf("[Route Manager] Done\n");
195 return NULL;
196}
197
198/* ============================================================================
199 * Main Application
200 * ========================================================================== */
201
202int main(void)
203{
204 rte_log_initialize();
205
206 printf("\n");
207 printf("═══════════════════════════════════════════════════════════════\n");
208 printf("IPC Publish-Subscribe Example\n");
209 printf("═══════════════════════════════════════════════════════════════\n");
210 printf("\n");
211
212 RTE_LOG_INFO("Creating pub-sub topic...");
213
214 /* Create topic */
215 rte_ipc_pubsub_topic_config_t topic_config = {
216 .topic_name = "track_status",
217 .message_size = sizeof(track_status_t),
218 .max_subscribers = 5
219 };
220
222 rte_status_t status = rte_ipc_pubsub_topic_create(&topic, &topic_config);
223
224 if (status != RTE_STATUS_OK) {
225 RTE_LOG_ERROR("Failed to create topic: %d", status);
226 return EXIT_FAILURE;
227 }
228
229 RTE_LOG_INFO("Creating subscribers...");
230
231 /* Create subscribers */
232 rte_ipc_pubsub_subscriber_t signal_subscriber, speed_subscriber, route_subscriber;
233
234 rte_ipc_pubsub_subscriber_config_t signal_config = {
235 .subscriber_name = "signal_manager",
236 .topic = topic,
237 .queue_depth = 5
238 };
239 rte_ipc_pubsub_subscribe(&signal_subscriber, &signal_config);
240
242 .subscriber_name = "speed_manager",
243 .topic = topic,
244 .queue_depth = 5
245 };
246 rte_ipc_pubsub_subscribe(&speed_subscriber, &speed_config);
247
249 .subscriber_name = "route_manager",
250 .topic = topic,
251 .queue_depth = 5
252 };
253 rte_ipc_pubsub_subscribe(&route_subscriber, &route_config);
254
255 RTE_LOG_INFO("Starting publisher and subscribers...");
256
257 /* Start threads */
258 pthread_t pub_thread, sig_thread, spd_thread, rte_thread;
259
260 pthread_create(&pub_thread, NULL, track_publisher_thread, &topic);
261 pthread_create(&sig_thread, NULL, signal_manager_thread, &signal_subscriber);
262 pthread_create(&spd_thread, NULL, speed_manager_thread, &speed_subscriber);
263 pthread_create(&rte_thread, NULL, route_manager_thread, &route_subscriber);
264
265 /* Wait for threads */
266 pthread_join(pub_thread, NULL);
267 pthread_join(sig_thread, NULL);
268 pthread_join(spd_thread, NULL);
269 pthread_join(rte_thread, NULL);
270
271 /* Cleanup */
272 RTE_LOG_INFO("Cleaning up...");
273 rte_ipc_pubsub_unsubscribe(&signal_subscriber);
274 rte_ipc_pubsub_unsubscribe(&speed_subscriber);
275 rte_ipc_pubsub_unsubscribe(&route_subscriber);
277
278 printf("\n");
279 printf("═══════════════════════════════════════════════════════════════\n");
280 printf("Example Complete\n");
281 printf("═══════════════════════════════════════════════════════════════\n");
282 printf("\n");
283
284 printf("Key Observations:\n");
285 printf("✓ Publisher (Track DB) sends status changes\n");
286 printf("✓ Three subscribers (Signal, Speed, Route) receive same message\n");
287 printf("✓ Each subscriber reacts independently\n");
288 printf("✓ Decoupled: Publisher doesn't know about subscribers\n");
289 printf("✓ Event-driven: Subscribers wake up when status changes\n");
290 printf("\n");
291
292 return EXIT_SUCCESS;
293}
rte_status_t
Common result/status codes.
Definition rte_status.h:27
@ RTE_STATUS_OK
Definition rte_status.h:28
@ RTE_STATUS_TIMEOUT
Definition rte_status.h:32
static void * speed_manager_thread(void *arg)
Speed Manager - Reacts to track status by updating speed limits.
static void * route_manager_thread(void *arg)
Route Manager - Reacts to track status by planning routes.
static void * track_publisher_thread(void *arg)
Simulate track status changes and publish.
static void * signal_manager_thread(void *arg)
Signal Manager - Reacts to track status by updating signals.
rte_status_t rte_ipc_pubsub_topic_destroy(rte_ipc_pubsub_topic_t topic)
Destroy a publish-subscribe topic.
rte_status_t rte_ipc_pubsub_receive(rte_ipc_pubsub_subscriber_t subscriber, void *message_out, size_t message_size, rte_duration_ms_t timeout_ms)
Receive a message from subscribed topic (blocking with timeout).
struct rte_ipc_pubsub_subscriber_s * rte_ipc_pubsub_subscriber_t
Subscriber handle for receiving from a topic.
rte_status_t rte_ipc_pubsub_unsubscribe(rte_ipc_pubsub_subscriber_t subscriber)
Unsubscribe from a topic.
struct rte_ipc_pubsub_topic_s * rte_ipc_pubsub_topic_t
Publish-subscribe topic handle.
rte_status_t rte_ipc_pubsub_subscribe(rte_ipc_pubsub_subscriber_t *subscriber_out, const rte_ipc_pubsub_subscriber_config_t *config)
Subscribe to a topic.
rte_status_t rte_ipc_pubsub_topic_create(rte_ipc_pubsub_topic_t *topic_out, const rte_ipc_pubsub_topic_config_t *config)
Create a publish-subscribe topic.
rte_status_t rte_ipc_pubsub_publish(rte_ipc_pubsub_topic_t topic, const void *message, size_t message_size)
Publish a message to all subscribers on a topic.
Configuration for a subscriber.
Configuration for a pub-sub topic.
Track status event (published to all subscribers).