diff --git a/src/bin/main_gui.rs b/src/bin/main_gui.rs index 0a7b2bc..b1db917 100644 --- a/src/bin/main_gui.rs +++ b/src/bin/main_gui.rs @@ -20,8 +20,6 @@ async fn main() { log::set_max_level(log::LevelFilter::Info); info!("Starting Bioz Impedance Visualizer..."); - let rt = Runtime::new().expect("Unable to create Runtime"); - // Enter the runtime so that `tokio::spawn` is available immediately. // let _enter = rt.enter(); @@ -52,7 +50,15 @@ async fn main() { // Log thread tokio::spawn(async move { log_data(log_rx, gui_logging_state_1).await }); + // TCP command server in separate thread + let rt = Runtime::new().expect("Unable to create Runtime"); + let tcp_run_impedancemeter_tx = run_impedancemeter_tx_clone.clone(); + std::thread::spawn(move || { + rt.block_on(bioz_host_rs::tcp::tcp_command_server(tcp_run_impedancemeter_tx)); + }); + // Execute the runtime in its own thread. + let rt = Runtime::new().expect("Unable to create Runtime"); std::thread::spawn(move || { rt.block_on(communicate_with_hardware( run_impedancemeter_rx, diff --git a/src/lib.rs b/src/lib.rs index 75b8bd4..c4aba97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,7 @@ pub mod client; pub mod app; pub mod communication; +pub mod tcp; pub mod plot; pub mod signals; pub mod logging; diff --git a/src/tcp.rs b/src/tcp.rs new file mode 100644 index 0000000..80a6ae0 --- /dev/null +++ b/src/tcp.rs @@ -0,0 +1,60 @@ +use tokio::net::TcpListener; +use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, BufWriter}; +use tokio::sync::mpsc::Sender; + +use crate::signals::StartStopSignal; + +pub async fn tcp_command_server(tx: Sender) { + let listener = TcpListener::bind("127.0.0.1:12345").await.unwrap(); + println!("TCP command server listening on 12345"); + + loop { + let (socket, addr) = listener.accept().await.unwrap(); + println!("Client connected: {:?}", addr); + + let tx = tx.clone(); + + tokio::spawn(async move { + let (reader, writer) = socket.into_split(); + + let mut reader = BufReader::new(reader); + let mut writer = BufWriter::new(writer); + let mut lines = reader.lines(); + + while let Ok(Some(line)) = lines.next_line().await { + println!("Received: {}", line); + + match parse_command(&line) { + Some(signal) => { + if tx.send(signal).await.is_ok() { + let _ = writer.write_all(b"OK\n").await; + } else { + let _ = writer.write_all(b"ERR internal channel failure\n").await; + break; + } + } + None => { + let _ = writer.write_all(b"ERR unknown command\n").await; + } + } + + let _ = writer.flush().await; + } + + println!("Client disconnected: {:?}", addr); + }); + } +} + +fn parse_command(line: &str) -> Option { + let parts: Vec<&str> = line.split_whitespace().collect(); + + match parts.as_slice() { + ["STOP"] => Some(StartStopSignal::Stop), + + _ => { + eprintln!("Unknown command: {}", line); + None + } + } +} \ No newline at end of file