### Server Example Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-service/README.md A basic example demonstrating how to set up a `ServiceServer` in Rust. ```APIDOC ## Server Example ### Description This example shows how to initialize eCAL, create a `ServiceServer`, add a 'mirror' method that echoes received data, and keep the server running. ### Code ```rust use rustecal::{Ecal, EcalComponents, ServiceServer}; use rustecal::service::types::MethodInfo; fn main() -> Result<(), Box> { Ecal::initialize(Some("mirror_server"), EcalComponents::DEFAULT, None)?; let mut server = ServiceServer::new("mirror_service")?; server.add_method("mirror", Box::new(|method: MethodInfo, req: &[u8]| { let request_str = String::from_utf8_lossy(req); println!("Received [{}]: {}", method.method_name, request_str); // Echo (mirror) the same bytes back req.to_vec() }))?; println!("mirror_service is running…"); while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` ``` -------------------------------- ### Client Example Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-service/README.md A basic example demonstrating how to set up a `ServiceClient` in Rust. ```APIDOC ## Client Example ### Description This example shows how to initialize eCAL, create a `ServiceClient`, and call the 'mirror' method on a remote service, handling responses and timeouts. ### Code ```rust use rustecal::{Ecal, EcalComponents, ServiceClient, ServiceRequest}; fn main() -> Result<(), Box> { Ecal::initialize(Some("mirror_client"), EcalComponents::DEFAULT, None)?; let client = ServiceClient::new("mirror_service")?; let request_data = b"Hello, Service!"; let timeout = Some(500); while Ecal::ok() { let request = ServiceRequest { payload: request_data.to_vec(), }; // Call the "mirror" method if let Some(response) = client.call("mirror", request, timeout) { // Extract the echoed payload let echoed = String::from_utf8_lossy(&response.payload); println!("Received response: {}", echoed); } else { println!("Service call timed out."); } std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` ``` -------------------------------- ### Create a Service Server with rustecal Source: https://github.com/eclipse-ecal/rustecal/blob/main/README.md Example of setting up a service server that registers and handles a 'reverse' method. The server remains active to process requests. ```rust use std::time::Duration; use rustecal::{Ecal, EcalComponents}; use rustecal::service::server::ServiceServer; use rustecal::service::types::MethodInfo; fn main() { // Initialize eCAL Ecal::initialize(Some("mirror server"), EcalComponents::DEFAULT, None).unwrap(); // create a service server for "mirror" let mut server = ServiceServer::new("mirror").unwrap(); // register the "reverse" method server .add_method( "reverse", Box::new(|_info: MethodInfo, req: &[u8]| { let mut reversed = req.to_vec(); reversed.reverse(); reversed }), ) .unwrap(); // keep the server alive to handle incoming calls while Ecal::ok() { std::thread::sleep(Duration::from_millis(100)); } // clean up and finalize eCAL Ecal::finalize(); } ``` -------------------------------- ### Publisher Example Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-types-string/README.md Example demonstrating how to publish StringMessage using TypedPublisher. ```APIDOC ## Publisher Example ### Description This example shows how to initialize eCAL, create a `TypedPublisher` for `StringMessage`, and send messages periodically. ### Method `TypedPublisher::::new()` `publisher.send()` ### Endpoint Not applicable (local eCAL communication) ### Parameters None directly for the example, but `TypedPublisher::new` takes a topic name. ### Request Example ```rust use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal_types_string::StringMessage; fn main() -> Result<(), Box> { Ecal::initialize(Some("string publisher"), EcalComponents::DEFAULT, None)?; let publisher = TypedPublisher::::new("hello")?; while Ecal::ok() { let message = StringMessage { data: "Hello from Rust".into() }; publisher.send(&message, Timestamp::Auto); std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` ### Response No direct response for the publisher itself, but messages are sent to the eCAL network. ``` -------------------------------- ### Subscriber Example Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-types-string/README.md Example demonstrating how to subscribe to StringMessage using TypedSubscriber and set a callback. ```APIDOC ## Subscriber Example ### Description This example shows how to initialize eCAL, create a `TypedSubscriber` for `StringMessage`, and process received messages using a callback. ### Method `TypedSubscriber::::new()` `subscriber.set_callback()` ### Endpoint Not applicable (local eCAL communication) ### Parameters None directly for the example, but `TypedSubscriber::new` takes a topic name. ### Request Example ```rust use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_string::StringMessage; fn main() -> Result<(), Box> { Ecal::initialize(Some("string subscriber"), EcalComponents::DEFAULT, None)?; let mut subscriber = TypedSubscriber::::new("hello")?; subscriber.set_callback(|message| { println!("Received: {}", message.payload.data) }); while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` ### Response Messages are received and processed by the callback function. The example prints the received message data. ``` -------------------------------- ### Create a Service Client with rustecal Source: https://github.com/eclipse-ecal/rustecal/blob/main/README.md Example of creating a service client to call a remote 'reverse' method. It sends requests and prints responses, with a delay between calls. ```rust use std::time::Duration; use rustecal::{Ecal, EcalComponents}; use rustecal::service::client::ServiceClient; use rustecal::service::types::ServiceRequest; fn main() { // Initialize eCAL Ecal::initialize(Some("mirror client"), EcalComponents::DEFAULT, None).unwrap(); // create a service client for "mirror" let client = ServiceClient::new("mirror").unwrap(); // call the "reverse" service until eCAL shuts down while Ecal::ok() { // prepare the request payload let request = ServiceRequest { payload: b"stressed".to_vec(), }; // send the request and print the response if any if let Some(response) = client.call("reverse", request, Some(1000)) { println!("Reversed: {}", String::from_utf8_lossy(&response.payload)); } else { println!("No response received."); } // throttle the request rate std::thread::sleep(Duration::from_secs(1)); } // clean up and finalize eCAL Ecal::finalize(); } ``` -------------------------------- ### Typed Publisher Example in Rust Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-pubsub/README.md Example demonstrating how to create a typed publisher for StringMessage and send messages periodically. Ensure eCAL is initialized before creating the publisher. ```rust use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal_types_string::StringMessage; fn main() -> Result<(), Box> { Ecal::initialize(Some("string publisher"), EcalComponents::DEFAULT, None)?; let publisher = TypedPublisher::::new("hello")?; while Ecal::ok() { let message = StringMessage { data: "Hello from Rust".into() }; publisher.send(&message, Timestamp::Auto); std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Subscribe to String Messages with rustecal Source: https://github.com/eclipse-ecal/rustecal/blob/main/README.md Example of creating a subscriber and setting a callback to process incoming string messages. Requires an active publisher. ```rust use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_string::StringMessage; fn main() { // Initialize eCAL Ecal::initialize(Some("hello subscriber"), EcalComponents::DEFAULT, None).unwrap(); // create a string subscriber on “hello” let mut subscriber = TypedSubscriber::::new("hello").unwrap(); // print each incoming message subscriber.set_callback(|message| { println!("Received: {}", message.payload.data) }); // keep the thread alive so callbacks can run while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(100)); } // clean up and finalize eCAL Ecal::finalize(); } ``` -------------------------------- ### Publish String Messages with rustecal Source: https://github.com/eclipse-ecal/rustecal/blob/main/README.md Example of creating a publisher and sending string messages. Ensure eCAL is initialized and running. ```rust use std::time::Duration; use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal::pubsub::publisher::Timestamp; use rustecal_types_string::StringMessage; fn main() { // Initialize eCAL Ecal::initialize(Some("hello publisher"), EcalComponents::DEFAULT, None).unwrap(); // create a string publisher on "hello" let publisher = TypedPublisher::::new("hello").unwrap(); // prepare the message to send let message = StringMessage { data: "Hello from Rust".into() }; // publish until eCAL shuts down while Ecal::ok() { publisher.send(&message, Timestamp::Auto); std::thread::sleep(Duration::from_millis(500)); } // clean up and finalize eCAL Ecal::finalize(); } ``` -------------------------------- ### Add rustecal to Cargo.toml Source: https://context7.com/eclipse-ecal/rustecal/llms.txt Specify rustecal and its features in your Cargo.toml file for installation. Choose the full installation or a minimal setup with specific features. ```toml # Full installation with all features (default) [dependencies] rustecal = "0.1" # Minimal installation with only pub/sub [dependencies] rustecal = { version = "0.1", default-features = false, features = ["pubsub"] } # With specific type support [dependencies] rustecal = "0.1" rustecal-types-string = "0.1" rustecal-types-bytes = "0.1" rustecal-types-protobuf = "0.1" rustecal-types-serde = "0.1" ``` -------------------------------- ### Protobuf Publisher Example Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/examples/protobuf.md This snippet demonstrates how to publish Protobuf messages using Rustecal. Ensure Protobuf types are correctly implemented with `IsProtobufType` and included via `include!(concat!(env!("OUT_DIR"), "/pb..rs"))`. ```rust use std::sync::Arc; use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal::pubsub::publisher::Timestamp; use rustecal_types_protobuf::{ProtobufMessage, IsProtobufType}; mod people { include!(concat!(env!("OUT_DIR"), "/pb.people.rs")); } mod animal { include!(concat!(env!("OUT_DIR"), "/pb.animal.rs")); } mod environment { include!(concat!(env!("OUT_DIR"), "/pb.environment.rs")); } use people::Person; impl IsProtobufType for Person {} fn main() -> Result<(), Box> { Ecal::initialize(Some("protobuf publisher"), EcalComponents::DEFAULT, None)?; let publisher = TypedPublisher::>::new("person")?; while Ecal::ok() { let person = Person { id: 1, name: "Alice".into(), ..Default::default() }; let message = ProtobufMessage { data : Arc::from(person) }; publisher.send(&message, Timestamp::Auto); std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Publisher Sample Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/api/zero_copy_messaging.md Example of a Rustecal publisher implementing zero-copy communication. It uses a custom `PayloadWriter` to send large byte arrays efficiently. ```APIDOC ## Publisher Sample ```rust use rustecal::{Configuration, Ecal, EcalComponents, TypedPublisher}; use rustecal_pubsub::PayloadWriter; use rustecal_pubsub::publisher::Timestamp; use rustecal_types_bytes::BytesMessage; /// A simple zero-copy writer that fills a buffer with a repeating pattern. pub struct CustomWriter { size: usize, counter: u8, } impl CustomWriter { pub fn new(size: usize) -> Self { Self { size, counter: 0 } } } impl PayloadWriter for CustomWriter { fn write_full(&mut self, buf: &mut [u8]) -> bool { if buf.len() < self.size { return false; } // fill entire buffer with 0xAA buf[..self.size].fill(0xAA); true } fn write_modified(&mut self, buf: &mut [u8]) -> bool { if buf.len() < self.size { return false; } // flip one byte each time let idx = (self.counter as usize) % self.size; buf[idx] ^= 0xFF; self.counter = self.counter.wrapping_add(1); true } fn get_size(&self) -> usize { self.size } } fn main() -> Result<(), Box> { // configure eCAL let mut cfg = Configuration::new()?; cfg.publisher.layer.shm.zero_copy_mode = true as i32; cfg.publisher.layer.shm.acknowledge_timeout_ms = 50; Ecal::initialize( Some("zero copy publisher"), EcalComponents::DEFAULT, Some(&cfg), )?; // create typed publisher let publisher: TypedPublisher = TypedPublisher::new("buffer")?; // prepare zero-copy payload writer let mut writer = CustomWriter::new(8 * 1024 * 1024); // 8 MB // send loop while Ecal::ok() { publisher.send_payload_writer(&mut writer, Timestamp::Auto); } // finalize ecal and clean up Ecal::finalize(); Ok(()) } ``` ``` -------------------------------- ### JSON Publisher Example in Rust Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-types-serde/README.md This example demonstrates how to publish JSON-encoded messages using the TypedPublisher with JsonMessage. Ensure eCAL is initialized before creating the publisher. ```rust use serde::{Serialize, Deserialize}; use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal_types_serde::JsonMessage; #[derive(Serialize, Deserialize, Clone, Debug)] struct MyData { msg: String, } fn main() -> Result<(), Box> { Ecal::initialize(Some("json publisher"), EcalComponents::DEFAULT, None)?; let publisher = TypedPublisher::>::new("hello_json")?; while Ecal::ok() { let payload = MyData { msg: "Hello from Rust".into() }; let message = JsonMessage::new(payload); publisher.send(&message, Timestamp::Auto); std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Protobuf Subscriber Example Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/examples/protobuf.md This snippet shows how to subscribe to Protobuf messages using Rustecal. It sets up a callback to process received messages. Ensure Protobuf types are correctly implemented with `IsProtobufType` and included via `include!(concat!(env!("OUT_DIR"), "/pb..rs"))`. ```rust use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_protobuf::{ProtobufMessage, IsProtobufType}; mod people { include!(concat!(env!("OUT_DIR"), "/pb.people.rs")); } mod animal { include!(concat!(env!("OUT_DIR"), "/pb.animal.rs")); } mod environment { include!(concat!(env!("OUT_DIR"), "/pb.environment.rs")); } use people::Person; impl IsProtobufType for Person {} fn main() -> Result<(), Box> { Ecal::initialize(Some("protobuf subscriber"), EcalComponents::DEFAULT, None)?; let mut subscriber = TypedSubscriber::>::new("person")?; subscriber.set_callback(|message| { println!("Received person: {}", message.payload.data.name) }); while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Zero-Copy Publisher Setup and Send Loop Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/api/zero_copy_messaging.md Configures eCAL for zero-copy mode and creates a `TypedPublisher` for `BytesMessage`. It then enters a loop to send data using the `CustomWriter`. ```rust use rustecal::{Configuration, Ecal, EcalComponents, TypedPublisher}; use rustecal_pubsub::PayloadWriter; use rustecal_pubsub::publisher::Timestamp; use rustecal_types_bytes::BytesMessage; fn main() -> Result<(), Box> { // configure eCAL let mut cfg = Configuration::new()?; cfg.publisher.layer.shm.zero_copy_mode = true as i32; cfg.publisher.layer.shm.acknowledge_timeout_ms = 50; Ecal::initialize( Some("zero copy publisher"), EcalComponents::DEFAULT, Some(&cfg), )?; // create typed publisher let publisher: TypedPublisher = TypedPublisher::new("buffer")?; // prepare zero-copy payload writer let mut writer = CustomWriter::new(8 * 1024 * 1024); // 8 MB // send loop while Ecal::ok() { publisher.send_payload_writer(&mut writer, Timestamp::Auto); } // finalize ecal and clean up Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Typed Subscriber Example in Rust Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-pubsub/README.md Example demonstrating how to create a typed subscriber for StringMessage and set a callback to process received messages. Ensure eCAL is initialized before creating the subscriber. ```rust use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_string::StringMessage; fn main() -> Result<(), Box> { Ecal::initialize(Some("string subscriber"), EcalComponents::DEFAULT, None)?; let mut subscriber = TypedSubscriber::::new("hello")?; subscriber.set_callback(|message| { println!("Received: {}", message.payload.data) }); while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Subscriber Sample Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/api/zero_copy_messaging.md Example of a Rustecal subscriber receiving zero-copy messages. It registers a callback to process data directly from shared memory. ```APIDOC ## Subscriber Sample ```rust use std::{thread, time::Duration}; use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_bytes::BytesMessage; fn main() -> Result<(), Box> { // initialize eCAL Ecal::initialize( Some("zero copy subscriber"), EcalComponents::DEFAULT, None, )?; // create typed subscriber let mut sub: TypedSubscriber = TypedSubscriber::new("buffer")?; // register zero-copy callback sub.set_callback(|received| { // borrow shared-memory payload let buffer: &[u8] = received.payload.data.as_ref(); // this line is just to demonstrate usage (it will kill the performance) println!("Received {} bytes", buffer.len()); }); // keep alive for callbacks while Ecal::ok() { thread::sleep(Duration::from_millis(100)); } // finalize ecal and clean up Ecal::finalize(); Ok(()) } ``` ``` -------------------------------- ### JSON Subscriber Example in Rust Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-types-serde/README.md This example shows how to subscribe to JSON-encoded messages using the TypedSubscriber with JsonMessage. A callback function is used to process received messages. ```rust use serde::{Serialize, Deserialize}; use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_serde::JsonMessage; #[derive(Serialize, Deserialize, Clone, Debug)] struct MyData { msg: String, } fn main() -> Result<(), Box> { Ecal::initialize(Some("json subscriber"), EcalComponents::DEFAULT, None)?; let mut subscriber = TypedSubscriber::>::new("hello_json")?; subscriber.set_callback(|message| { println!("Received: {}", message.payload.data.msg); }); while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Configure rustecal Features in Cargo.toml Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal/README.md Customize the enabled features for the rustecal meta-crate in your Cargo.toml. This example disables default features and explicitly enables only the 'pubsub' feature. ```toml [dependencies] rustecal = { version = "0.1", default-features = false, features = ["pubsub"] } ``` -------------------------------- ### Publish Binary Data with BytesMessage Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-types-bytes/README.md This example demonstrates how to publish raw binary data using BytesMessage. Ensure eCAL is initialized and a TypedPublisher for BytesMessage is created. The loop sends a 1024-byte buffer repeatedly, incrementing a counter. ```rust use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal_types_bytes::BytesMessage; fn main() -> Result<(), Box> { Ecal::initialize(Some("blob publisher"), EcalComponents::DEFAULT, None)?; let publisher = TypedPublisher::::new("blob")?; let mut counter = 0u8; while Ecal::ok() { let buf = vec![counter; 1024]; counter = counter.wrapping_add(1); let message = BytesMessage { data: buf.into() }; publisher.send(&message, Timestamp::Auto); std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Publish String Messages with rustecal Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-types-string/README.md Example of publishing UTF-8 string messages using TypedPublisher and StringMessage. Ensure eCAL is initialized before creating the publisher. ```rust use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal_types_string::StringMessage; fn main() -> Result<(), Box> { Ecal::initialize(Some("string publisher"), EcalComponents::DEFAULT, None)?; let publisher = TypedPublisher::::new("hello")?; while Ecal::ok() { let message = StringMessage { data: "Hello from Rust".into() }; publisher.send(&message, Timestamp::Auto); std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Publish String Messages Source: https://context7.com/eclipse-ecal/rustecal/llms.txt Publishes type-safe string messages on a specified topic. This example demonstrates creating a typed publisher, sending messages, and querying its state. ```rust use std::time::Duration; use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal::pubsub::publisher::Timestamp; use rustecal_types_string::StringMessage; fn main() -> Result<(), Box> { Ecal::initialize(Some("string_publisher"), EcalComponents::DEFAULT, None)?; // Create a typed publisher for string messages on the "hello" topic let publisher = TypedPublisher::::new("hello")?; let mut counter = 0; while Ecal::ok() { // Create and send a message let message = StringMessage { data: format!("Hello #{} from Rust", counter).into() }; let success = publisher.send(&message, Timestamp::Auto); // Query publisher state println!( "Sent to {} subscribers on topic '{}': {}", publisher.get_subscriber_count(), publisher.get_topic_name().unwrap_or_default(), success ); counter += 1; std::thread::sleep(Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Get eCAL System Snapshot Source: https://context7.com/eclipse-ecal/rustecal/llms.txt Retrieves and prints a snapshot of the current eCAL system state, including processes, publishers, subscribers, servers, and clients. Requires the monitoring component to be initialized. ```rust use rustecal::{Ecal, EcalComponents}; use rustecal_core::monitoring::Monitoring; use std::{thread, time::Duration}; fn main() -> Result<(), Box> { // Initialize with monitoring component Ecal::initialize(Some("system_monitor"), EcalComponents::MONITORING, None)?; while Ecal::ok() { let snapshot = Monitoring::get_snapshot()?; println!("=== eCAL System Snapshot ==="); println!("\nProcesses ({})", snapshot.processes.len()); for proc in &snapshot.processes { println!(" - {} (PID: {})", proc.unit_name, proc.process_id); } println!("\nPublishers ({})", snapshot.publishers.len()); for pub_info in &snapshot.publishers { println!(" - Topic: {}, Type: {}", pub_info.topic_name, pub_info.data_type_name); } println!("\nSubscribers ({})", snapshot.subscribers.len()); for sub_info in &snapshot.subscribers { println!(" - Topic: {}", sub_info.topic_name); } println!("\nServers ({})", snapshot.servers.len()); for server in &snapshot.servers { println!(" - Service: {}", server.service_name); } println!("\nClients ({})", snapshot.clients.len()); for client in &snapshot.clients { println!(" - Service: {}", client.service_name); } thread::sleep(Duration::from_secs(2)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Set ECAL_HOME Environment Variable (Windows) Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/setup/ecal_installation.md Set the ECAL_HOME environment variable to the eCAL installation directory on Windows. This is required for rustecal to find the necessary eCAL files. ```powershell $env:ECAL_HOME = "C:\eCAL" ``` -------------------------------- ### Serve rustecal documentation locally Source: https://github.com/eclipse-ecal/rustecal/blob/main/README.md Command to serve the rustecal documentation locally using mdbook. Navigate to the docs directory first. ```bash cd docs/ mdbook serve ``` -------------------------------- ### Create a Rustecal Service Server Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-service/README.md Implement a service server by initializing eCAL, creating a ServiceServer instance, and adding methods with closure-based handlers. The server runs in a loop, processing requests. ```rust use rustecal::{Ecal, EcalComponents, ServiceServer}; use rustecal::service::types::MethodInfo; fn main() -> Result<(), Box> { Ecal::initialize(Some("mirror_server"), EcalComponents::DEFAULT, None)?; let mut server = ServiceServer::new("mirror_service")?; server.add_method("mirror", Box::new(|method: MethodInfo, req: &[u8]| { let request_str = String::from_utf8_lossy(req); println!("Received [{}] request: {}", method.method_name, request_str); // Echo (mirror) the same bytes back req.to_vec() }))?; println!("mirror_service is running…"); while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Registering Service Methods in Rust Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/api/service_server.md Create a ServiceServer and add methods with associated callbacks. Callbacks take MethodInfo and a byte slice request, returning a Vec response. Ensure the server name is unique. ```rust use rustecal::service::server::ServiceServer; use rustecal::service::types::MethodInfo; let mut server = ServiceServer::new("mirror")?; server.add_method("echo", Box::new(|_info: MethodInfo, request: &[u8]| { request.to_vec() }))?; server.add_method("reverse", Box::new(|_info, request| { let mut reversed = request.to_vec(); reversed.reverse(); reversed }))?; ``` -------------------------------- ### Implement Mirror Service Server in Rust Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/examples/service_server.md This snippet shows how to initialize ECAL, create a ServiceServer, add a 'mirror' method that echoes received bytes, and keep the server running. Ensure ECAL is initialized before creating the server. ```rust use rustecal::{Ecal, EcalComponents, ServiceServer}; use rustecal::service::types::MethodInfo; fn main() -> Result<(), Box> { Ecal::initialize(Some("mirror_server"), EcalComponents::DEFAULT, None)?; let mut server = ServiceServer::new("mirror_service")?; server.add_method("mirror", Box::new(|method: MethodInfo, req: &[u8]| { let request_str = String::from_utf8_lossy(req); println!("Received [{}] request: {}", method.method_name, request_str); // Echo (mirror) the same bytes back req.to_vec() }))?; println!("mirror_service is running…"); while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Call Mirror Service with Rustecal Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/examples/service_client.md Initializes ecal, creates a service client, and repeatedly calls the 'mirror' method on the 'mirror_service'. Handles timeouts and prints received responses. Ensure the Mirror Service is running before executing. ```rust use rustecal::{Ecal, EcalComponents, ServiceClient, ServiceRequest}; fn main() -> Result<(), Box> { Ecal::initialize(Some("mirror_client"), EcalComponents::DEFAULT, None)?; let client = ServiceClient::new("mirror_service")?; let request_data = b"Hello, Service!"; let timeout = Some(500); while Ecal::ok() { let request = ServiceRequest { payload: request_data.to_vec(), }; // Call the "mirror" method if let Some(response) = client.call("mirror", request, timeout) { // Extract the echoed payload let echoed = String::from_utf8_lossy(&response.payload); println!("Received response: {}", echoed); } else { println!("Service call timed out."); } std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Create a Rustecal Service Client Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-service/README.md Implement a service client by initializing eCAL, creating a ServiceClient instance, and calling remote methods with optional timeouts. The client sends requests and processes responses. ```rust use rustecal::{Ecal, EcalComponents, ServiceClient, ServiceRequest}; fn main() -> Result<(), Box> { Ecal::initialize(Some("mirror_client"), EcalComponents::DEFAULT, None)?; let client = ServiceClient::new("mirror_service")?; let request_data = b"Hello, Service!"; let timeout = Some(500); while Ecal::ok() { let request = ServiceRequest { payload: request_data.to_vec(), }; // Call the "mirror" method if let Some(response) = client.call("mirror", request, timeout) { // Extract the echoed payload let echoed = String::from_utf8_lossy(&response.payload); println!("Received response: {}", echoed); } else { println!("Service call timed out."); } std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Initialize and Finalize eCAL System in Rust Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/api/ecal.md Demonstrates the basic lifecycle management of the eCAL system. Ensure to call finalize when done to clean up resources. ```rust use rustecal::{Ecal, EcalComponents}; fn main() -> Result<(), Box> { Ecal::initialize(Some("my ecal app"), EcalComponents::DEFAULT, None)?; // use publishers, subscribers, clients, server Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Implement RPC ServiceServer with Multiple Methods Source: https://context7.com/eclipse-ecal/rustecal/llms.txt Use ServiceServer to register multiple RPC methods with closures. Ensure Ecal is initialized before creating the server. The server runs in a loop, processing requests until Ecal::ok() returns false. ```rust use std::time::Duration; use rustecal::{Ecal, EcalComponents}; use rustecal::service::server::ServiceServer; use rustecal::service::types::MethodInfo; fn main() -> Result<(), Box> { Ecal::initialize(Some("math_server"), EcalComponents::DEFAULT, None)?; let mut server = ServiceServer::new("calculator")?; // Echo method - returns input unchanged server.add_method("echo", Box::new(|info: MethodInfo, request: &[u8]| { println!("[{}] Echo called with {} bytes", info.method_name, request.len()); request.to_vec() }))?; // Reverse method - reverses byte order server.add_method("reverse", Box::new(|_info: MethodInfo, request: &[u8]| { let mut result = request.to_vec(); result.reverse(); result }))?; // Add method - adds two i32 numbers server.add_method("add", Box::new(|_info: MethodInfo, request: &[u8]| { if request.len() >= 8 { let a = i32::from_le_bytes(request[0..4].try_into().unwrap()); let b = i32::from_le_bytes(request[4..8].try_into().unwrap()); let sum = a + b; sum.to_le_bytes().to_vec() } else { vec![] // Invalid request } }))?; println!("Calculator service running..."); while Ecal::ok() { std::thread::sleep(Duration::from_millis(100)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Add rustecal-pubsub to Cargo.toml Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-pubsub/README.md Add this to your Cargo.toml file to include the rustecal-pubsub dependency. ```toml [dependencies] rustecal-pubsub = "0.1" ``` -------------------------------- ### Connect to eCAL Service Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/api/service_client.md Instantiate a ServiceClient to connect to a specific eCAL service by its name. Ensure the service is available at runtime. ```rust use rustecal::service::client::ServiceClient; let client = ServiceClient::new("mirror")?; ``` -------------------------------- ### Subscribe to Protobuf Messages in Rust Source: https://context7.com/eclipse-ecal/rustecal/llms.txt Shows how to subscribe to Protobuf messages using `TypedSubscriber` and process received data. Requires a running publisher. ```rust use std::sync::Arc; use rustecal::{Ecal, EcalComponents, TypedPublisher, TypedSubscriber}; use rustecal::pubsub::publisher::Timestamp; use rustecal_types_protobuf::{ProtobufMessage, IsProtobufType}; // Include generated protobuf code (from build.rs using prost) mod people { include!(concat!(env!("OUT_DIR"), "/pb.people.rs")); } use people::Person; impl IsProtobufType for Person {} // Subscriber fn subscribe_protobuf() -> Result<(), Box> { Ecal::initialize(Some("protobuf_subscriber"), EcalComponents::DEFAULT, None)?; let mut subscriber = TypedSubscriber::>::new("person")?; subscriber.set_callback(|message| { let person = &message.payload.data; println!("Received: {} (id={}, email={})", person.name, person.id, person.email); }); while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(100)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Publish JSON Message in Rust Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/examples/json.md Initializes ECAL, creates a typed publisher for JSON messages, and continuously sends 'Hello from Rust' messages. Ensure the MyData struct is serializable and deserializable. ```rust use serde::{Serialize, Deserialize}; use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal::pubsub::publisher::Timestamp; use rustecal_types_serde::JsonMessage; #[derive(Serialize, Deserialize, Clone, Debug)] struct MyData { msg: String, } fn main() -> Result<(), Box> { Ecal::initialize(Some("json publisher"), EcalComponents::DEFAULT, None)?; let publisher = TypedPublisher::>::new("hello_json")?; while Ecal::ok() { let payload = MyData { msg: "Hello from Rust".into() }; let message = JsonMessage::new(payload); publisher.send(&message, Timestamp::Auto); std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Publish Protobuf Messages in Rust Source: https://context7.com/eclipse-ecal/rustecal/llms.txt Demonstrates publishing Protobuf messages using the `ProtobufMessage` type and `TypedPublisher`. Ensure generated protobuf code is included. ```rust use std::sync::Arc; use rustecal::{Ecal, EcalComponents, TypedPublisher, TypedSubscriber}; use rustecal::pubsub::publisher::Timestamp; use rustecal_types_protobuf::{ProtobufMessage, IsProtobufType}; // Include generated protobuf code (from build.rs using prost) mod people { include!(concat!(env!("OUT_DIR"), "/pb.people.rs")); } use people::Person; impl IsProtobufType for Person {} // Publisher fn publish_protobuf() -> Result<(), Box> { Ecal::initialize(Some("protobuf_publisher"), EcalComponents::DEFAULT, None)?; let publisher = TypedPublisher::>::new("person")?; let mut id = 1; while Ecal::ok() { let person = Person { id, name: format!("Person_{}", id), email: format!("person{}@example.com", id), ..Default::default() }; let message = ProtobufMessage { data: Arc::from(person) }; publisher.send(&message, Timestamp::Auto); id += 1; std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Initialize eCAL Runtime Source: https://context7.com/eclipse-ecal/rustecal/llms.txt Initializes the eCAL runtime system. This must be called before using any publishers, subscribers, or services. Various component flags can be enabled. ```rust use rustecal::{Ecal, EcalComponents, Configuration}; fn main() -> Result<(), Box> { // Basic initialization with default components Ecal::initialize(Some("my_application"), EcalComponents::DEFAULT, None)?; // Your application logic here while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(100)); } Ecal::finalize(); Ok(()) } // Available EcalComponents flags: // - EcalComponents::NONE - Disable all components // - EcalComponents::PUBLISHER - Enable publish interface // - EcalComponents::SUBSCRIBER - Enable subscribe interface // - EcalComponents::SERVICE - Enable RPC-style communication // - EcalComponents::MONITORING - Enable monitoring component // - EcalComponents::LOGGING - Enable logging // - EcalComponents::TIMESYNC - Enable time synchronization // - EcalComponents::DEFAULT - Publisher + Subscriber + Service + Logging + Timesync // - EcalComponents::ALL - All components enabled ``` -------------------------------- ### Add rustecal-types-serde to Cargo.toml Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-types-serde/README.md Add this dependency to your workspace Cargo.toml file to include the rustecal-types-serde crate. ```toml [dependencies] rustecal-types-serde = "0.1" ``` -------------------------------- ### eCAL Utility Functions Source: https://context7.com/eclipse-ecal/rustecal/llms.txt Demonstrates the use of utility functions provided by the Ecal struct, such as checking operational status, initialization state, component initialization, and retrieving version information. ```rust use rustecal::{Ecal, EcalComponents}; fn main() -> Result<(), Box> { Ecal::initialize(Some("utility_demo"), EcalComponents::DEFAULT, None)?; // Check if eCAL is operational if Ecal::ok() { println!("eCAL is running"); } // Check initialization state if Ecal::is_initialized() { println!("eCAL has been initialized"); } // Check specific components if Ecal::is_component_initialized(EcalComponents::PUBLISHER) { println!("Publisher component is active"); } // Get version information println!("eCAL Version: {}", Ecal::version_string()); println!("Build Date: {}", Ecal::version_date_string()); let version = Ecal::version_struct(); println!("Version struct: {}.{}.{}", version.major, version.minor, version.patch); Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Subscribe to JSON Message in Rust Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/examples/json.md Initializes ECAL, creates a typed subscriber for JSON messages, and sets a callback to print the received message's content. The subscriber listens on the 'hello_json' topic. ```rust use serde::{Serialize, Deserialize}; use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_serde::JsonMessage; #[derive(Serialize, Deserialize, Clone, Debug)] struct MyData { msg: String, } fn main() -> Result<(), Box> { Ecal::initialize(Some("json subscriber"), EcalComponents::DEFAULT, None)?; let mut subscriber = TypedSubscriber::>::new("hello_json")?; subscriber.set_callback(|message| { println!("Received: {}", message.payload.data.msg); }); while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Add rustecal to Cargo.toml Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal/README.md Include the rustecal meta-crate as a dependency in your project's Cargo.toml file. This will enable all default features, including pub/sub and service APIs. ```toml [dependencies] rustecal = "0.1" ``` -------------------------------- ### Add rustecal-service Dependency Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-service/README.md Add the rustecal-service crate to your project's Cargo.toml file to include its functionality. ```toml [dependencies] rustecal-service = "0.1" ``` -------------------------------- ### Emit and Retrieve Log Messages Source: https://context7.com/eclipse-ecal/rustecal/llms.txt Demonstrates emitting log messages at different severity levels (Info, Debug, Warning, Error) and retrieving them from the eCAL logging system. Requires the logging component to be initialized. ```rust use rustecal::{Ecal, EcalComponents}; use rustecal_core::log::Log; use rustecal_core::log_level::LogLevel; use std::{thread, time::Duration}; fn main() -> Result<(), Box> { // Initialize with logging component Ecal::initialize(Some("logging_demo"), EcalComponents::LOGGING, None)?; // Emit log messages at different levels Log::log(LogLevel::Info, "Application started successfully"); Log::log(LogLevel::Debug, "Debug information for troubleshooting"); Log::log(LogLevel::Warning, "This is a warning message"); Log::log(LogLevel::Error, "An error occurred"); // Retrieve and display log entries while Ecal::ok() { let entries = Log::get_logging()?; if !entries.is_empty() { println!("=== Log Entries ({}) ===", entries.len()); for entry in &entries { println!( "[{:?}] {} - {}", entry.level, entry.unit_name, entry.message ); } } thread::sleep(Duration::from_secs(1)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Add rustecal-types-bytes to Cargo.toml Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-types-bytes/README.md Add this dependency to your workspace's Cargo.toml file to include the rustecal-types-bytes crate. ```toml rustecal-types-bytes = "0.1" ``` -------------------------------- ### Subscribe to Binary Messages with Rustecal Source: https://github.com/eclipse-ecal/rustecal/blob/main/docs/src/examples/binary.md This subscriber receives byte buffers published via ECAL. It sets up a callback to process incoming messages and prints the size of the received byte data. ECAL must be initialized before creating the subscriber. ```rust use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_bytes::BytesMessage; fn main() -> Result<(), Box> { Ecal::initialize(Some("blob subscriber"), EcalComponents::DEFAULT, None)?; let mut subscriber = TypedSubscriber::::new("blob")?; subscriber.set_callback(|message| { println!("Received blob of {} bytes", message.payload.data.len()); }); while Ecal::ok() { std::thread::sleep(std::time::Duration::from_millis(500)); } Ecal::finalize(); Ok(()) } ``` -------------------------------- ### Add rustecal-types-string to Cargo.toml Source: https://github.com/eclipse-ecal/rustecal/blob/main/rustecal-types-string/README.md Add this dependency to your workspace's Cargo.toml file to include the rustecal-types-string crate. ```toml [dependencies] rustecal-types-string = "0.1" ```