36#include "rte/channel_link/rte_channel.h"
37#include "rte/voter/rte_voter.h"
38#include "rte/status/rte_status.h"
48 uint8_t data[10][256];
64 memcpy(q->data[q->write_idx], data, size);
65 q->write_idx = (q->write_idx + 1) % 10;
81 memcpy(data, q->data[q->read_idx], 256);
82 q->read_idx = (q->read_idx + 1) % 10;
94 uint32_t packets_sent;
95 uint32_t packets_recv;
99static tcp_channel_t tcp_ch_0 = {.socket = 0, .connected =
true};
103 if (ch->socket < 0 || !ch->connected) {
123 if (ch->socket < 0 || !ch->connected) {
152 CHANNEL_TYPE_SHARED_MEMORY,
165 .type = CHANNEL_TYPE_SHARED_MEMORY,
166 .impl.shm = &shm_queue_0,
170 .type = CHANNEL_TYPE_TCP,
171 .impl.tcp = &tcp_ch_0,
189 case CHANNEL_TYPE_SHARED_MEMORY:
190 return shm_send(ch->impl.shm, data, size);
192 case CHANNEL_TYPE_TCP:
193 return tcp_send(ch->impl.tcp, data, size);
207 uint32_t timeout_ms __attribute__((unused)))
216 case CHANNEL_TYPE_SHARED_MEMORY:
217 return shm_recv(ch->impl.shm, data, size);
219 case CHANNEL_TYPE_TCP:
220 return tcp_recv(ch->impl.tcp, data, size);
236 uint32_t speed_limit_kmh;
237 uint32_t target_distance_m;
238 uint8_t emergency_stop;
241#define CHANNEL_COUNT 2U
254 static void *
const osadapter_handles[CHANNEL_COUNT] = { &g_channel_0, &g_channel_1 };
267 printf(
"ERROR: Failed to initialize voter: %d\n", rc);
271 for (i = 0; i < CHANNEL_COUNT; i++) {
280 printf(
"ERROR: Failed to initialize channel %u: %d\n", i, rc);
286 printf(
"ERROR: Failed to register channel %u: %d\n", i, rc);
291 printf(
"Voter initialized with 2oo2 voting over 2 channels\n");
292 printf(
" Channel 0: Shared Memory (local standby)\n");
293 printf(
" Channel 1: TCP/IP (remote standby)\n");
302 printf(
"\n>>> Broadcasting train command:\n");
303 printf(
" Command ID: %u\n", cmd->command_id);
304 printf(
" Speed Limit: %u km/h\n", cmd->speed_limit_kmh);
305 printf(
" Distance: %u m\n", cmd->target_distance_m);
306 printf(
" E-Stop: %s\n", cmd->emergency_stop ?
"YES" :
"NO");
310 printf(
"Send failed: %d (channel fault detected)\n", rc);
314 printf(
"Sent to both channels (atomic broadcast)\n");
324 size_t bytes_received = 0;
326 printf(
"\n<<< Receiving train command (with voting)...\n");
332 printf(
"Receive failed: %d (voting result: %d)\n", rc, vote_result);
336 printf(
"Both channels agreed on data:\n");
337 printf(
" Command ID: %u\n", cmd_out->command_id);
338 printf(
" Speed Limit: %u km/h\n", cmd_out->speed_limit_kmh);
347 printf(
"\n=== Channel Health Report ===\n");
349 for (uint32_t i = 0; i < CHANNEL_COUNT; i++) {
354 printf(
" Channel %u: Error reading health\n", i);
358 printf(
" Channel %u:\n", i);
359 printf(
" Healthy: %s\n", health.
is_healthy ?
"YES" :
"NO");
364 uint32_t healthy_count = 0;
365 uint32_t total_disagreements = 0;
367 printf(
" Total healthy: %u/%u\n", healthy_count, CHANNEL_COUNT);
368 printf(
" Total disagreements: %u\n", total_disagreements);
370 if (healthy_count < CHANNEL_COUNT) {
371 printf(
" WARNING: Redundancy compromised!\n");
380 printf(
"========================================\n");
381 printf(
"Voted Channel: Dual Transport Example\n");
382 printf(
"========================================\n");
392 printf(
"\n--- Test 1: Normal Operation ---\n");
395 .speed_limit_kmh = 80,
396 .target_distance_m = 5000,
401 printf(
"Send failed\n");
407 printf(
"\n--- Test 2: One Channel Healthy ---\n");
408 tcp_ch_0.connected =
false;
409 printf(
"TCP connection lost\n");
411 cmd.command_id = 1002;
413 printf(
"Send failed (expected, channel down)\n");
419 printf(
"\n--- Test 3: Recovery ---\n");
420 tcp_ch_0.connected =
true;
421 printf(
"TCP connection restored\n");
423 cmd.command_id = 1003;
425 printf(
"Send failed\n");
434 for (uint32_t i = 0; i < CHANNEL_COUNT; i++) {
437 printf(
"\n========================================\n");
438 printf(
"Example completed\n");
439 printf(
"========================================\n");
rte_status_t
Common result/status codes.
@ RTE_STATUS_INVALID_PARAM
@ RTE_STATUS_HARDWARE_FAULT
@ RTE_STATUS_RESOURCE_EXHAUSTED
rte_status_t rte_channel_destroy(rte_channel_t *handle)
Destroys a vital channel instance.
rte_status_t rte_channel_get_health(const rte_channel_t *handle, rte_channel_health_t *out_health)
Queries this channel's health statistics.
rte_channel_storage_t rte_channel_t
Opaque handle to a vital channel instance.
rte_status_t rte_channel_init(rte_channel_storage_t *storage, const rte_channel_config_t *config)
Initializes one vital channel over a caller-supplied transport.
rte_voter_storage_t rte_voter_t
Opaque handle to a voter instance.
rte_status_t rte_voter_get_aggregated_health(const rte_voter_t *voter, uint32_t *healthy_count, uint32_t *total_disagreements)
Aggregated health across every registered channel.
rte_status_t rte_voter_register_channel(rte_voter_t *voter, rte_channel_t *channel)
Registers one already-initialized channel with this voter.
rte_status_t rte_voter_destroy(rte_voter_t *voter)
Destroys a voter instance.
rte_voting_result_t
Outcome of one rte_voter_receive() call.
rte_status_t rte_voter_send(rte_voter_t *voter, const void *data, size_t data_size)
Broadcasts data to every registered, healthy channel.
rte_status_t rte_voter_init(rte_voter_storage_t *storage, const rte_voter_config_t *config)
Initializes a voter with zero registered channels.
rte_status_t rte_voter_receive(rte_voter_t *voter, void *data, size_t data_size, rte_voting_result_t *result, size_t *bytes_received)
Receives from every registered, healthy channel and votes.
Configuration for rte_channel_init().
Health statistics for one vital channel.
uint32_t receive_error_count
uint32_t send_error_count
Configuration for rte_voter_init().
void * disagreement_context
uint32_t channel_timeout_ms
void(*) on_disagreement(void *context, rte_voting_result_t result)
rte_voting_strategy_t voting_strategy
static rte_status_t receive_train_command(rte_voter_t *voter, train_command_t *cmd_out)
Receive a train command via the voter (with 2oo2 voting).
static rte_status_t example_setup_dual_redundancy(rte_channel_t channels[CHANNEL_COUNT], rte_voter_t *voter)
Example: Initialize dual-transport channels plus a 2oo2 voter.
channel_type_t
Opaque channel type that hides whether it's SHM or TCP.
static rte_status_t send_train_command(rte_voter_t *voter, const train_command_t *cmd)
Send a train command to every registered channel (atomic broadcast).
static void monitor_channel_health(rte_channel_t channels[CHANNEL_COUNT], rte_voter_t *voter)
Monitor channel health and detect faults.
static rte_status_t channel_backend_recv(void *channel_handle, void *data, size_t size, uint32_t timeout_ms __attribute__((unused)))
OSAdapter receive callback for rte_channel (dispatches to transport).
static rte_status_t channel_backend_send(void *channel_handle, const void *data, size_t size)
OSAdapter send callback for rte_channel (dispatches to transport).