diff --git a/Cargo.lock b/Cargo.lock index 46f0eff..c41bb22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,8 +160,15 @@ dependencies = [ ] [[package]] -name = "minimal-update-server-client" +name = "minimal-update-client-server" version = "1.0.0" +dependencies = [ + "crossbeam", + "ctrlc", + "ncomm-core", + "ncomm-executors", + "ncomm-update-clients-and-servers", +] [[package]] name = "ncomm-clients-and-servers" diff --git a/Cargo.toml b/Cargo.toml index 6d9c799..fda109a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ members = [ "ncomm-clients-and-servers", "ncomm-update-clients-and-servers", "examples/minimal-client-server", - "examples/minimal-update-server-client", + "examples/minimal-update-client-server", "examples/minimal-publisher-subscriber", ] @@ -19,6 +19,7 @@ default-members = [ "ncomm-clients-and-servers", "ncomm-update-clients-and-servers", ] +resolver = "2" [workspace.package] name = "ncomm" diff --git a/examples/minimal-client-server/Cargo.toml b/examples/minimal-client-server/Cargo.toml index f5539bf..909adbf 100644 --- a/examples/minimal-client-server/Cargo.toml +++ b/examples/minimal-client-server/Cargo.toml @@ -17,4 +17,4 @@ ncomm-executors = { workspace = true } ncomm-clients-and-servers = { workspace = true } crossbeam = { workspace = true } ctrlc = { workspace = true } -rand = { workspace = true } \ No newline at end of file +rand = { workspace = true } diff --git a/examples/minimal-update-server-client/Cargo.toml b/examples/minimal-update-client-server/Cargo.toml similarity index 56% rename from examples/minimal-update-server-client/Cargo.toml rename to examples/minimal-update-client-server/Cargo.toml index d194358..1f78fb8 100644 --- a/examples/minimal-update-server-client/Cargo.toml +++ b/examples/minimal-update-client-server/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "minimal-update-server-client" -description = "Minimal Update Server and Client example based on the [Ros 2 Tutorial](https://docs.ros.org/en/foxy/Tutorials/Intermediate/Writing-an-Action-Server-Client/Cpp.html)" +name = "minimal-update-client-server" +description = "Minimal Update Client and Server example based on the [Ros 2 Tutorial](https://docs.ros.org/en/foxy/Tutorials/Intermediate/Writing-an-Action-Server-Client/Cpp.html)" version.workspace = true edition.workspace = true license.workspace = true @@ -12,3 +12,8 @@ authors.workspace = true categories.workspace = true [dependencies] +ncomm-core = { workspace = true } +ncomm-executors = { workspace = true } +ncomm-update-clients-and-servers = { workspace = true } +crossbeam = { workspace = true } +ctrlc = { workspace = true } diff --git a/examples/minimal-update-client-server/src/fibonacci_update_client.rs b/examples/minimal-update-client-server/src/fibonacci_update_client.rs new file mode 100644 index 0000000..a9f7cb5 --- /dev/null +++ b/examples/minimal-update-client-server/src/fibonacci_update_client.rs @@ -0,0 +1,62 @@ +//! +//! A Simple Update Client Example that sends a request for the nth term in the +//! fibonacci series. +//! + +use super::{FibonacciRequest, FibonacciUpdate, FibonacciResponse}; + +use ncomm_core::{Node, UpdateClient}; +use ncomm_update_clients_and_servers::local::LocalUpdateClient; + +/// A simple update client node that sends a request for the nth term in the +/// fibonacci series, printing the numbers in the series before receiving the nth +/// number in the series +pub struct FibonacciUpdateClient { + update_client: LocalUpdateClient, +} + +impl FibonacciUpdateClient { + /// Create a new Fibonacci Update Client + pub fn new(update_client: LocalUpdateClient) -> Self { + Self { + update_client, + } + } + + /// Print the update messages received + pub fn handle_updates(&mut self) { + let updates = self.update_client.poll_for_updates(); + for update in updates.iter() { + if let Ok((_request, update)) = update { + println!("Last Num: {} --- Current Num: {}", update.last_num, update.current_num); + } + } + } + + /// Print the response message received and send a new request for the 10th order of + /// a fibonacci sequence + pub fn handle_response(&mut self) { + let responses = self.update_client.poll_for_responses(); + for response in responses.iter() { + if let Ok((request, response)) = response { + println!("f(10) = {}", response.num); + self.update_client.send_request(request.clone()).unwrap(); + } + } + } +} + +impl Node for FibonacciUpdateClient { + fn get_update_delay_us(&self) -> u128 { + 100_000 + } + + fn start(&mut self) { + self.update_client.send_request(FibonacciRequest { order: 10 }).unwrap(); + } + + fn update(&mut self) { + self.handle_updates(); + self.handle_response(); + } +} \ No newline at end of file diff --git a/examples/minimal-update-client-server/src/fibonacci_update_server.rs b/examples/minimal-update-client-server/src/fibonacci_update_server.rs new file mode 100644 index 0000000..1181390 --- /dev/null +++ b/examples/minimal-update-client-server/src/fibonacci_update_server.rs @@ -0,0 +1,94 @@ +//! +//! An update server example that calculates the nth term in the +//! fibonacci sequence, updating a client with each sequence of terms +//! into the series +//! + +use super::{FibonacciRequest, FibonacciUpdate, FibonacciResponse}; + +use ncomm_core::{Node, UpdateServer}; +use ncomm_update_clients_and_servers::local::{LocalUpdateClient, LocalUpdateServer}; + +/// An update server node that calculates the nth term in the fibonacci +/// sequence +/// +/// Note: for this example, the update server only expects a single client but +/// it would be trivial to make this update server capable of handling multiple +/// clients. +pub struct FibonacciUpdateServer { + last_num: u128, + current_num: u128, + order: u128, + current_order: u128, + current_request: Option<(String, FibonacciRequest)>, + update_server: LocalUpdateServer, +} + +impl FibonacciUpdateServer { + /// Create a new fibonacci update server + pub fn new() -> Self { + Self { + last_num: 1, + current_num: 1, + order: 1, + current_order: 1, + current_request: None, + update_server: LocalUpdateServer::new(), + } + } + + /// Create a client for the fibonacci update server node + pub fn create_client(&mut self, client_name: String) -> LocalUpdateClient { + self.update_server.create_update_client(client_name) + } + + /// Check for requests + fn handle_requests(&mut self) { + if let Some(Ok((client, request))) = self.update_server.poll_for_requests().last() { + self.current_request = Some((client.clone(), request.clone())); + self.order = request.order; + self.last_num = 1; + self.current_num = 1; + self.current_order = 1; + } + } + + /// Send Updates for the current client + fn send_updates(&mut self) { + if let Some((client_id, request)) = self.current_request.as_ref() { + let next_num = self.last_num + self.current_num; + self.last_num = self.current_num; + self.current_num = next_num; + self.update_server.send_update( + client_id.clone(), + &request, + FibonacciUpdate { last_num: self.last_num, current_num: self.current_num } + ).unwrap(); + self.current_order += 1; + } + } + + /// Send final response for the current client + fn send_response(&mut self) { + if self.current_request.is_some() && self.current_order == self.order { + let (client_id, request) = self.current_request.take().unwrap(); + self.update_server.send_response( + client_id, + request, + FibonacciResponse { num: self.current_num } + ).unwrap(); + } + } +} + +impl Node for FibonacciUpdateServer { + fn get_update_delay_us(&self) -> u128 { + 100_000 + } + + fn update(&mut self) { + self.handle_requests(); + self.send_updates(); + self.send_response(); + } +} \ No newline at end of file diff --git a/examples/minimal-update-client-server/src/main.rs b/examples/minimal-update-client-server/src/main.rs new file mode 100644 index 0000000..e1f87d2 --- /dev/null +++ b/examples/minimal-update-client-server/src/main.rs @@ -0,0 +1,66 @@ +//! +//! Example for a minimal update client and server where +//! the server requests a a fibonacci value of some order and +//! the server responds with updates containing the last and current +//! value in a fibonacci series before it finds the fibonacci value of +//! given degree which is returned as a response +//! + +#![deny(missing_docs)] + +use ncomm_core::Executor; +use ncomm_executors::SimpleExecutor; + +use crossbeam::channel::unbounded; + +pub mod fibonacci_update_client; +use fibonacci_update_client::FibonacciUpdateClient; + +pub mod fibonacci_update_server; +use fibonacci_update_server::FibonacciUpdateServer; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +/// A request asking for a the nth order of the fibonacci sequence. +pub struct FibonacciRequest { + /// The nth term of the fibonacci sequence to compute + pub order: u128, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +/// An update containing the current last number and the current number +/// the update server has currently computed. +pub struct FibonacciUpdate { + /// The order n-1 term of the fibonacci sequence + pub last_num: u128, + /// The order n term of the fibonacci sequence + pub current_num: u128, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +/// A response containing the number at a given order of the fibonacci +/// sequence. +pub struct FibonacciResponse { + /// The order n term of the fibonacci sequence + pub num: u128, +} + +fn main() { + let mut update_server_node = FibonacciUpdateServer::new(); + let update_client_node = FibonacciUpdateClient::new( + update_server_node.create_client(String::from("Fibonacci Update Client")) + ); + + let (tx, rx) = unbounded(); + ctrlc::set_handler(move || tx.send(true).expect("Unable to send data")) + .expect("Error setting Ctrl-C handler"); + + let mut executor = SimpleExecutor::new_with( + rx, + vec![ + Box::new(update_client_node), + Box::new(update_server_node), + ] + ); + + executor.update_loop(); +} diff --git a/examples/minimal-update-server-client/src/main.rs b/examples/minimal-update-server-client/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/examples/minimal-update-server-client/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/examples/minimal_update_service_client/.gitignore b/examples/minimal_update_service_client/.gitignore deleted file mode 100644 index ea8c4bf..0000000 --- a/examples/minimal_update_service_client/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/examples/minimal_update_service_client/Cargo.lock b/examples/minimal_update_service_client/Cargo.lock deleted file mode 100644 index 9abd61f..0000000 --- a/examples/minimal_update_service_client/Cargo.lock +++ /dev/null @@ -1,129 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "ctrlc" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e" -dependencies = [ - "nix", - "windows-sys", -] - -[[package]] -name = "libc" -version = "0.2.144" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" - -[[package]] -name = "minimal_update_service_client" -version = "0.1.1" -dependencies = [ - "ncomm", -] - -[[package]] -name = "ncomm" -version = "0.2.0" -dependencies = [ - "ctrlc", -] - -[[package]] -name = "nix" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" -dependencies = [ - "bitflags", - "cfg-if", - "libc", - "static_assertions", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/examples/minimal_update_service_client/Cargo.toml b/examples/minimal_update_service_client/Cargo.toml deleted file mode 100644 index cb87129..0000000 --- a/examples/minimal_update_service_client/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "minimal_update_service_client" -version = "0.1.1" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -ncomm = { path = "../../", version = "0.2.0" } \ No newline at end of file diff --git a/examples/minimal_update_service_client/src/fibonacci_update_client.rs b/examples/minimal_update_service_client/src/fibonacci_update_client.rs deleted file mode 100644 index c46fdee..0000000 --- a/examples/minimal_update_service_client/src/fibonacci_update_client.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::fibonacci_update_server::{FibonacciRequest, FibonacciUpdate, FibonacciResponse}; - -use ncomm::update_client_server::{UpdateClient, local::LocalUpdateClient}; -use ncomm::node::Node; - -pub struct FibonacciUpdateClient<'a> { - name: &'a str, - update_client: LocalUpdateClient -} - -impl<'a> FibonacciUpdateClient<'a> { - pub fn new(name: &'a str, update_client: LocalUpdateClient) -> Self { - Self { name, update_client } - } -} - -impl<'a> Node for FibonacciUpdateClient<'a> { - fn name(&self) -> String { String::from(self.name) } - - fn get_update_delay(&self) -> u128 { 10u128 } - - fn start(&mut self) { - self.update_client.send_request(FibonacciRequest { order: 10 }).unwrap(); - } - - fn update(&mut self) { - if let Some(update) = self.update_client.receive_update() { - println!("Received Update:"); - println!("Last Num: {} --- Current Num: {}", update.last_num, update.current_num); - } - - if let Some(response) = self.update_client.receive_response() { - println!("f(10) = {}", response.num); - } - } - - fn shutdown(&mut self) {} - - fn debug(&self) -> String { - format!( - "FIbonacci Update Client:\n{}", - self.name() - ) - } -} \ No newline at end of file diff --git a/examples/minimal_update_service_client/src/fibonacci_update_server.rs b/examples/minimal_update_service_client/src/fibonacci_update_server.rs deleted file mode 100644 index 8ecb062..0000000 --- a/examples/minimal_update_service_client/src/fibonacci_update_server.rs +++ /dev/null @@ -1,80 +0,0 @@ -use ncomm::update_client_server::{UpdateServer, local::{LocalUpdateClient, LocalUpdateServer}}; -use ncomm::node::Node; - -#[derive(PartialEq, Clone)] -pub struct FibonacciRequest { - pub order: u128, -} - -#[derive(PartialEq, Clone)] -pub struct FibonacciUpdate { - pub last_num: u128, - pub current_num: u128, -} - -#[derive(PartialEq, Clone)] -pub struct FibonacciResponse { - pub num: u128, -} - -pub struct FibonacciUpdateServer<'a> { - name: &'a str, - last_num: u128, - current_num: u128, - order: u128, - current_order: u128, - update_server: LocalUpdateServer, -} - -impl<'a> FibonacciUpdateServer<'a> { - pub fn new(name: &'a str) -> Self { - Self { name, last_num: 0, current_num: 0, order: 0, current_order: 0, update_server: LocalUpdateServer::new() } - } - - pub fn create_client(&mut self, client_name: String) -> LocalUpdateClient { - self.update_server.create_update_client(client_name) - } -} - -impl<'a> Node for FibonacciUpdateServer<'a> { - fn name(&self) -> String { String::from(self.name) } - - fn get_update_delay(&self) -> u128 { 10u128 } - - fn start(&mut self) {} - - fn update(&mut self) { - let requests = self.update_server.receive_requests(); - - if requests.len() > 0 { - self.last_num = 1; - self.current_num = 1; - self.current_order = 1; - self.order = requests[0].1.order; - } else { - if self.current_order < self.order { - let next_num = self.last_num + self.current_num; - self.last_num = self.current_num; - self.current_num = next_num; - for client in self.update_server.get_clients() { - self.update_server.send_update(client, FibonacciUpdate { last_num: self.last_num, current_num: self.current_num }); - } - self.current_order += 1; - } else if self.current_order == self.order { - for client in self.update_server.get_clients() { - self.update_server.send_response(client, FibonacciResponse { num: self.current_num }); - } - self.current_order += 1; - } - } - } - - fn shutdown(&mut self) {} - - fn debug(&self) -> String { - format!( - "Fibonacci Update Server:\n{}", - self.name() - ) - } -} \ No newline at end of file diff --git a/examples/minimal_update_service_client/src/main.rs b/examples/minimal_update_service_client/src/main.rs deleted file mode 100644 index eddc3ab..0000000 --- a/examples/minimal_update_service_client/src/main.rs +++ /dev/null @@ -1,24 +0,0 @@ -extern crate ncomm; - -use std::sync::mpsc; - -use ncomm::executor::{Executor, SingleThreadedExecutor, simple_executor::SimpleExecutor}; - -pub mod fibonacci_update_server; -pub mod fibonacci_update_client; - -use fibonacci_update_server::FibonacciUpdateServer; -use fibonacci_update_client::FibonacciUpdateClient; - -fn main() { - let (_interrupt_tx, interrupt_rx) = mpsc::channel(); - - let mut server = FibonacciUpdateServer::new("fibonacci update server"); - let mut client = FibonacciUpdateClient::new("fibonacci update client", server.create_client(String::from("fibonacci update client"))); - let mut executor = SimpleExecutor::new(interrupt_rx); - - executor.add_node(&mut server); - executor.add_node(&mut client); - executor.start(); - executor.update_for_seconds(1); -}