diff --git a/agent/lib/src/external_api/mod.rs b/agent/lib/src/external_api/mod.rs index 908db95..e3a6fa2 100644 --- a/agent/lib/src/external_api/mod.rs +++ b/agent/lib/src/external_api/mod.rs @@ -1,2 +1,3 @@ pub mod model; +pub mod comms; pub mod service; diff --git a/agent/lib/src/external_api/model.rs b/agent/lib/src/external_api/model.rs index 5120c36..b78410c 100644 --- a/agent/lib/src/external_api/model.rs +++ b/agent/lib/src/external_api/model.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -#[derive(Deserialize, Serialize, Debug)] +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] pub struct FileModel { pub filename: String, pub content: String, @@ -11,3 +11,129 @@ pub struct CodeEntry { pub files: Vec, pub script: Vec, // All commands to execute at startup } + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] +pub enum Type { + Status, + Request, + Response, +} + +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] +pub enum Code { + Run, + Ok, +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct StatusMessage { + pub r#type: Type, + pub code: Code, +} + +impl StatusMessage { + pub fn new() -> StatusMessage { + StatusMessage { + r#type: Type::Status, + code: Code::Ok, + } + } +} + +impl Default for StatusMessage { + fn default() -> Self { + Self::new() + } +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct ResponseStep { + pub command: String, + pub result: i32, + pub stdout: String, + pub stderr: String, + pub enable_output: bool, +} + +impl ResponseStep { + pub fn new( + command: String, + result: i32, + stdout: String, + stderr: String, + enable_output: bool, + ) -> ResponseStep { + ResponseStep { + command, + result, + stdout, + stderr, + enable_output, + } + } +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct ResponseData { + pub id: String, + pub steps: Vec, +} + +impl ResponseData { + pub fn new(id: String, steps: Vec) -> ResponseData { + ResponseData { id, steps } + } +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct ResponseMessage { + pub r#type: Type, + pub code: Code, + pub data: ResponseData, +} + +impl ResponseMessage { + pub fn new(data: ResponseData) -> ResponseMessage { + ResponseMessage { + r#type: Type::Response, + code: Code::Run, + data, + } + } +} + +#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)] +pub struct RequestStep { + pub command: String, + pub enable_output: bool, +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct RequestData { + pub id: String, + pub files: Vec, + pub steps: Vec, +} + +impl RequestData { + pub fn new(id: String, files: Vec, steps: Vec) -> RequestData { + RequestData { id, files, steps } + } +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct RequestMessage { + pub r#type: Type, + pub code: Code, + pub data: RequestData, +} + +impl RequestMessage { + pub fn new(data: RequestData) -> RequestMessage { + RequestMessage { + r#type: Type::Request, + code: Code::Run, + data, + } + } +} diff --git a/agent/lib/src/external_api/service.rs b/agent/lib/src/external_api/service.rs index 36c11e9..eadeb09 100644 --- a/agent/lib/src/external_api/service.rs +++ b/agent/lib/src/external_api/service.rs @@ -1,7 +1,8 @@ use anyhow::{anyhow, Result}; -use log::{error, info}; +use log::{error, info, debug, trace}; -use super::model::CodeEntry; +use super::model::{RequestMessage, ResponseMessage, StatusMessage}; +use super::comms::{Message, MESSAGE_SIZE_NB_BYTES}; pub struct ExternalApi { serial_path: String, @@ -16,7 +17,7 @@ impl ExternalApi { } } - pub fn read_from_serial(&mut self) -> Result { + pub fn read_from_serial(&mut self) -> Result { info!("Reading from serial port: {}", self.serial_path); // Open the serial port @@ -25,20 +26,62 @@ impl ExternalApi { .map_err(|e| anyhow!("Failed to open serial port: {}", e))?; // Create a buffer to hold the data + let mut data_size: usize = 0; + let mut size_buffer: [u8; MESSAGE_SIZE_NB_BYTES] = [0; MESSAGE_SIZE_NB_BYTES]; + let mut got_size = false; + let mut buf = [0; 128]; + let mut bytes_read: usize = 0; // Create the final vector to hold the data let mut data_received: Vec = Vec::new(); - let mut find_delimiter = false; + //we read the buffer and retrieve the first 8 bytes which are the size of the message + while !got_size { + match serial.read(&mut size_buffer) { + Ok(t) => { + if t == 0 { + break; + } - while !find_delimiter { + bytes_read += t; + data_received.extend_from_slice(&size_buffer[..t]); + + trace!("Received {} bytes", t); + trace!("Size buffer: {:?}", data_received.clone()); + + if bytes_read >= MESSAGE_SIZE_NB_BYTES { + got_size = true; + + let size_string = String::from_utf8( + data_received.clone() + ).map_err( + |e| anyhow!("Failed to get message size as string: {}", e) + )?; + + trace!("Size string: {}", size_string); + + data_size = size_string.parse::().map_err( + |e| anyhow!("Failed to parse length of message: {}", e) + )?; + + data_received.drain(..MESSAGE_SIZE_NB_BYTES); + } + } + Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => (), + Err(e) => error!("{:?}", e), + } + } + + bytes_read = 0; + + while bytes_read < data_size { match serial.read(&mut buf) { Ok(t) => { if t > 0 { - info!("Buffer received {:?}", &buf[..t]); - find_delimiter = - self.append_data_before_delimiter(&buf, &mut data_received)?; + bytes_read += t; + data_received.extend_from_slice(&buf[..t]); + debug!("Received {} bytes", t); } } Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => (), @@ -46,10 +89,13 @@ impl ExternalApi { } } - info!("Final received data: {:?}", data_received); + debug!("Final received data: {:?}", data_received); + debug!("Total bytes read {:?}", bytes_read); let code_entry = self.parse_json_payload(&data_received)?; + info!("Code entry: {:?}", code_entry); + // Flush the serial port serial .flush() @@ -58,37 +104,36 @@ impl ExternalApi { Ok(code_entry) } - pub fn append_data_before_delimiter( - &mut self, - buf: &[u8], - data_received: &mut Vec, - ) -> Result { - // find char 1c (record separator) in the buffer - if let Some(i) = buf.iter().position(|&r| r == 0x1c) { - // Split the buffer at the position of the record separator - let (data_to_add, _) = buf.split_at(i); - - // Add the data to the data vector - data_received.extend_from_slice(data_to_add); - - info!("Delimiter found at index: {}", i); - - Ok(true) - } else { - // Add the data to the data vector - data_received.extend_from_slice(&buf[..buf.len()]); - Ok(false) - } - } - - pub fn parse_json_payload(&mut self, data: &[u8]) -> Result { + pub fn parse_json_payload(&mut self, data: &[u8]) -> Result { // Convert the data vector to a codeEntry struct - let code_entry: CodeEntry = serde_json::from_slice(data) + let request_message: RequestMessage = serde_json::from_slice(data) .map_err(|e| anyhow!("Failed to parse JSON payload: {}", e))?; - info!("Code entry: {:?}", code_entry); + info!("Code request message: {:?}", request_message); - Ok(code_entry) + Ok(request_message) + } + + pub fn send_status_message(&mut self) -> Result<()> { + let status_message: StatusMessage = StatusMessage::new(); + let status_message_json = serde_json::to_string(&status_message) + .map_err(|e| anyhow!("Failed to serialize status message: {}", e))?; + self.write_to_serial(&status_message_json)?; + Ok(()) + } + + pub fn send_response_message(&mut self, response_message: ResponseMessage) -> Result<()> { + let code_json = serde_json::to_string(&response_message) + .map_err(|e| anyhow!("Failed to stringify response message : {}", e))?; + + // Write the JSON to the serial port + self.write_to_serial(&code_json)?; + + info!( + "Response message written to serial port: {:?}", + response_message + ); + Ok(()) } pub fn write_to_serial(&mut self, data: &str) -> Result<()> { @@ -98,7 +143,8 @@ impl ExternalApi { .map_err(|e| anyhow!("Failed to open serial port: {}", e))?; // Conver the string to a byte array - let buf = data.as_bytes(); + let message = Message::new(data.to_string()).to_bytes(); + let buf = message.as_slice(); // Write the byte array to the serial port serial @@ -118,6 +164,8 @@ mod tests { use anyhow::Result; + use crate::external_api::model::{Code, FileModel, RequestStep, Type}; + use super::ExternalApi; #[test] @@ -126,32 +174,66 @@ mod tests { // Data vector with the following JSON payload: // { - // "files": [ + // "type": "Request", + // "code": "Run", + // "data": { + // "id": "4bf68974-c315-4c41-aee2-3dc2920e76e9", + // "files": [ + // { + // "filename": "src/index.js", + // "content": "console.log('Hello World!');" + // } + // ], + // "steps": [ // { - // "filename": "test.py", - // "content": "print('Hello World')" + // "command": "node src/index.js", + // "enable_output": true // } - // ], - // "script": [ - // "python3 test.py" - // ] - // } + // ] + // } + // } let data = [ - 123, 10, 32, 32, 34, 102, 105, 108, 101, 115, 34, 58, 32, 91, 10, 32, 32, 32, 32, 123, - 10, 32, 32, 32, 32, 32, 32, 34, 102, 105, 108, 101, 110, 97, 109, 101, 34, 58, 32, 34, - 116, 101, 115, 116, 46, 112, 121, 34, 44, 10, 32, 32, 32, 32, 32, 32, 34, 99, 111, 110, - 116, 101, 110, 116, 34, 58, 32, 34, 112, 114, 105, 110, 116, 40, 39, 72, 101, 108, 108, - 111, 32, 87, 111, 114, 108, 100, 39, 41, 34, 10, 32, 32, 32, 32, 125, 10, 32, 32, 93, - 44, 10, 32, 32, 34, 115, 99, 114, 105, 112, 116, 34, 58, 32, 91, 10, 32, 32, 32, 32, - 34, 112, 121, 116, 104, 111, 110, 51, 32, 116, 101, 115, 116, 46, 112, 121, 34, 10, 32, - 32, 93, 10, 32, 32, 10, 125, + 123, 10, 32, 32, 34, 116, 121, 112, 101, 34, 58, 32, 34, 82, 101, 113, 117, 101, 115, + 116, 34, 44, 10, 32, 32, 34, 99, 111, 100, 101, 34, 58, 32, 34, 82, 117, 110, 34, 44, + 10, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 123, 10, 32, 32, 32, 32, 34, 105, 100, + 34, 58, 32, 34, 52, 98, 102, 54, 56, 57, 55, 52, 45, 99, 51, 49, 53, 45, 52, 99, 52, + 49, 45, 97, 101, 101, 50, 45, 51, 100, 99, 50, 57, 50, 48, 101, 55, 54, 101, 57, 34, + 44, 10, 32, 32, 32, 32, 34, 102, 105, 108, 101, 115, 34, 58, 32, 91, 10, 32, 32, 32, + 32, 32, 32, 123, 10, 32, 32, 32, 32, 32, 32, 32, 32, 34, 102, 105, 108, 101, 110, 97, + 109, 101, 34, 58, 32, 34, 115, 114, 99, 47, 105, 110, 100, 101, 120, 46, 106, 115, 34, + 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 34, 99, 111, 110, 116, 101, 110, 116, 34, 58, + 32, 34, 99, 111, 110, 115, 111, 108, 101, 46, 108, 111, 103, 40, 39, 72, 101, 108, 108, + 111, 32, 87, 111, 114, 108, 100, 33, 39, 41, 59, 34, 10, 32, 32, 32, 32, 32, 32, 125, + 10, 32, 32, 32, 32, 93, 44, 10, 32, 32, 32, 32, 34, 115, 116, 101, 112, 115, 34, 58, + 32, 91, 10, 32, 32, 32, 32, 32, 32, 123, 10, 32, 32, 32, 32, 32, 32, 32, 32, 34, 99, + 111, 109, 109, 97, 110, 100, 34, 58, 32, 34, 110, 111, 100, 101, 32, 115, 114, 99, 47, + 105, 110, 100, 101, 120, 46, 106, 115, 34, 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 34, + 101, 110, 97, 98, 108, 101, 95, 111, 117, 116, 112, 117, 116, 34, 58, 32, 116, 114, + 117, 101, 10, 32, 32, 32, 32, 32, 32, 125, 10, 32, 32, 32, 32, 93, 10, 32, 32, 125, 10, + 125, ]; - let code_entry = internal_api.parse_json_payload(&data)?; - assert_eq!(code_entry.files[0].filename, "test.py"); - assert_eq!(code_entry.files[0].content, "print('Hello World')"); - assert_eq!(code_entry.script[0], "python3 test.py"); + let request_message = internal_api.parse_json_payload(&data)?; + + let files = vec![FileModel { + filename: "src/index.js".to_string(), + content: "console.log('Hello World!');".to_string(), + }]; + + let steps = vec![RequestStep { + command: "node src/index.js".to_string(), + enable_output: true, + }]; + + assert_eq!(request_message.r#type, Type::Request); + assert_eq!(request_message.code, Code::Run); + assert_eq!( + request_message.data.id, + "4bf68974-c315-4c41-aee2-3dc2920e76e9" + ); + assert_eq!(request_message.data.files[0], files[0]); + assert_eq!(request_message.data.steps[0], steps[0]); Ok(()) } @@ -177,80 +259,4 @@ mod tests { Ok(()) } - - #[test] - fn test_data_cut_before_delimiter() -> Result<()> { - let mut internal_api = ExternalApi::new("".to_string(), 0); - - let data = [97, 98, 99, 28, 1, 2, 3, 4, 5, 6, 7]; - let mut data_received: Vec = Vec::new(); - - let find_demiliter = - internal_api.append_data_before_delimiter(&data, &mut data_received)?; - - assert!(find_demiliter); - assert_eq!(data_received, [97, 98, 99]); - - Ok(()) - } - - #[test] - fn test_data_transferred_without_delimiter() -> Result<()> { - let mut internal_api = ExternalApi::new("".to_string(), 0); - - let data = [97, 98, 99, 1, 2, 3, 4, 5, 6, 7]; - let mut data_received: Vec = Vec::new(); - - let find_demiliter = - internal_api.append_data_before_delimiter(&data, &mut data_received)?; - - assert!(!find_demiliter); - assert_eq!(data_received, [97, 98, 99, 1, 2, 3, 4, 5, 6, 7]); - - Ok(()) - } - - #[test] - fn test_data_transferred_multiple_time() -> Result<()> { - let mut internal_api = ExternalApi::new("".to_string(), 0); - - let data = [97, 98, 99]; - let data2 = [1, 2, 3, 4, 5, 6, 7]; - let mut data_received: Vec = Vec::new(); - - let find_demiliter = - internal_api.append_data_before_delimiter(&data, &mut data_received)?; - let find_demiliter2 = - internal_api.append_data_before_delimiter(&data2, &mut data_received)?; - - assert!(!find_demiliter); - assert!(!find_demiliter2); - assert_eq!(data_received, [97, 98, 99, 1, 2, 3, 4, 5, 6, 7]); - - Ok(()) - } - - #[test] - fn test_data_transferred_with_delimiter() -> Result<()> { - let mut internal_api = ExternalApi::new("".to_string(), 0); - - let data = [97, 98, 99]; - let data2 = [1, 2, 3, 4, 5, 6, 7]; - let data3 = [8, 9, 10, 28, 11, 12, 13]; - let mut data_received: Vec = Vec::new(); - - let find_demiliter = - internal_api.append_data_before_delimiter(&data, &mut data_received)?; - let find_demiliter2 = - internal_api.append_data_before_delimiter(&data2, &mut data_received)?; - let find_demiliter3 = - internal_api.append_data_before_delimiter(&data3, &mut data_received)?; - - assert!(!find_demiliter); - assert!(!find_demiliter2); - assert!(find_demiliter3); - assert_eq!(data_received, [97, 98, 99, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); - - Ok(()) - } } diff --git a/agent/lib/src/internal_api/model.rs b/agent/lib/src/internal_api/model.rs index f159194..0ea8bf9 100644 --- a/agent/lib/src/internal_api/model.rs +++ b/agent/lib/src/internal_api/model.rs @@ -35,13 +35,3 @@ impl CodeReturn { } } } - -#[derive(Debug)] -pub enum InternalError { - CmdSpawn, - ChildWait(std::io::Error), - ChildExitError(i32), - InvalidExitCode, - StdoutRead, - StderrRead, -} diff --git a/agent/lib/src/internal_api/service.rs b/agent/lib/src/internal_api/service.rs index 81df8b6..662d04a 100644 --- a/agent/lib/src/internal_api/service.rs +++ b/agent/lib/src/internal_api/service.rs @@ -1,19 +1,26 @@ -use std::{process::Command, fs::File, path::{PathBuf, Path}}; -use anyhow::{anyhow, Result}; +use super::model::CodeReturn; +use crate::{ + external_api::model::{RequestMessage, ResponseData, ResponseMessage, ResponseStep}, + internal_api::model::FileModel, +}; +use anyhow::{anyhow, Ok, Result}; use log::{error, info}; -use crate::{external_api::model::CodeEntry, internal_api::model::FileModel}; use std::io::Write; -use super::model::{CodeReturn, InternalError}; +use std::{ + fs::File, + path::{Path, PathBuf}, + process::Command, +}; const WORKSPACE_PATH: &str = "/tmp"; pub struct InternalApi { - pub code_entry: CodeEntry, + pub request_message: RequestMessage, } impl InternalApi { - pub fn new(code_entry: CodeEntry) -> Self { - Self { code_entry } + pub fn new(request_message: RequestMessage) -> Self { + Self { request_message } } pub fn create_workspace(&mut self) -> Result<()> { @@ -23,7 +30,7 @@ impl InternalApi { let mut file_models: Vec = Vec::new(); let root_path = PathBuf::from(WORKSPACE_PATH); - self.code_entry.files.iter().for_each(|file| { + self.request_message.data.files.iter().for_each(|file| { let mut file_path = PathBuf::from(&file.filename); file_path.pop(); @@ -94,48 +101,71 @@ impl InternalApi { Ok(()) } - pub fn write_log(&self) -> String { - "Hello".to_string() + pub fn run(&mut self) -> Result { + info!("Running all steps"); + let mut steps: Vec = Vec::new(); + + // For each commands in the request, run it + let steps_to_process = self.request_message.data.steps.clone(); + + for step in steps_to_process { + let command = step.command.as_str(); + let code_return = self.run_one(command)?; + + // Hide Stdout if enable_output is false + let stdout = if step.enable_output { + code_return.stdout + } else { + "".to_string() + }; + let response_step = ResponseStep::new( + command.to_string(), + code_return.exit_code, + stdout, + code_return.stderr, + step.enable_output, + ); + + steps.push(response_step); + } + + let data: ResponseData = ResponseData::new(self.request_message.data.id.clone(), steps); + let response_message = ResponseMessage::new(data); + + Ok(response_message) } - pub fn run(&mut self) -> Result { - info!("Running code"); - - // Running the latest command in vector for now - + pub fn run_one(&mut self, command: &str) -> Result { + info!("Running command : {}", command); + let child_process = Command::new("/bin/sh") - .args(["-c", - self.code_entry.script.last().ok_or( - InternalError::CmdSpawn - )?.as_str() - ]) + .args(["-c", command]) .current_dir(WORKSPACE_PATH) .output() - .map_err(|_|InternalError::CmdSpawn)?; + .map_err(|e| anyhow!("Failed to spawn command : {}", e))?; - info!("Code execution finished, gathering outputs and exit code"); + let exit_code = child_process + .status + .code() + .ok_or_else(|| anyhow!("Failed to retrieve exit_code"))?; + let stdout = String::from_utf8(child_process.stdout) + .map_err(|e| anyhow!("Failed to retrieve stdout stream : {}", e))?; + let stderr = String::from_utf8(child_process.stderr) + .map_err(|e| anyhow!("Failed to retrieve stderr stream : {}", e))?; - let exit_code = child_process.status.code().ok_or( - InternalError::InvalidExitCode - )?; - let stdout = String::from_utf8(child_process.stdout).map_err( - |_| InternalError::StdoutRead - )?; - let stderr = String::from_utf8(child_process.stderr).map_err( - |_| InternalError::StderrRead - )?; + let code_return = CodeReturn::new(stdout, stderr, exit_code); - Ok(CodeReturn::new(stdout, stderr, exit_code)) + info!("Code execution finished: {:?}", code_return); + Ok(code_return) } - } #[cfg(test)] mod tests { + use super::*; + use crate::external_api::model::{FileModel, RequestData, RequestStep}; use std::fs::File; use std::io::Read; - use crate::external_api::model::FileModel; - use super::*; fn random_usize(max: usize) -> usize { let mut f = File::open("/dev/urandom").unwrap(); @@ -154,7 +184,7 @@ mod tests { let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; let mut string = String::new(); - for _ in 0..len { + for _ in 0..len { string.push(chars.chars().nth(random_usize(chars.len() - 1)).unwrap()); } @@ -163,20 +193,29 @@ mod tests { #[test] fn workload_runs_correctly() { - let entry = CodeEntry { - files: vec![], - script: vec![String::from("echo 'This is stdout' && echo 'This is stderr' >&2")], + let files: Vec = Vec::new(); + let mut steps: Vec = Vec::new(); + let step = RequestStep { + command: "echo 'This is stdout' && echo 'This is stderr' >&2".to_string(), + enable_output: true, }; + steps.push(step); + let request_data = RequestData::new( + "4bf68974-c315-4c41-aee2-3dc2920e76e9".to_string(), + files, + steps, + ); + let request_message = RequestMessage::new(request_data); - - let mut api = InternalApi::new(entry); // Empty code entry to avoid borrowing issues - // since the same object is used in the `run` method + let mut api = InternalApi::new(request_message); let res = api.run().unwrap(); - assert_eq!(res.exit_code, 0); - assert_eq!(res.stderr, "This is stderr\n"); - assert_eq!(res.stdout, "This is stdout\n"); + assert_eq!(res.data.steps[0].result, 0); + assert_eq!(res.data.steps[0].stderr, "This is stderr\n"); + assert_eq!(res.data.steps[0].stdout, "This is stdout\n"); + assert_eq!(res.data.id, "4bf68974-c315-4c41-aee2-3dc2920e76e9"); + assert!(res.data.steps[0].enable_output); } #[test] @@ -186,19 +225,32 @@ mod tests { base_dir.push("main.sh"); let path = base_dir.into_os_string().into_string().unwrap(); + let files: Vec = vec![FileModel { + filename: path.clone(), + content: "Hello World!".to_string(), + }]; + let steps: Vec = Vec::new(); + let request_data = RequestData::new( + "4bf68974-c315-4c41-aee2-3dc2920e76e9".to_string(), + files, + steps, + ); + let request_message = RequestMessage::new(request_data); + + InternalApi::new(request_message) + .create_workspace() + .unwrap(); - let entry = CodeEntry { - files: vec![ - FileModel { - filename: path.clone(), - content: "#!/bin/sh\necho -n 'Some outpout'".to_string() - } - ], - script: vec![path.clone()], - }; + assert!(Path::new(&path).exists()); - InternalApi::new(entry).create_workspace().unwrap(); + //Check that the file contains the specified content + let mut file = File::open(&path).unwrap(); + let mut buffer = [0; 12]; + file.read_exact(&mut buffer[..]).unwrap(); - assert!(Path::new(&path).exists()); + // Convert buffer to string + let content = String::from_utf8(buffer.to_vec()).unwrap(); + assert!(file.metadata().unwrap().is_file()); + assert_eq!(content, "Hello World!"); } -} \ No newline at end of file +} diff --git a/agent/src/main.rs b/agent/src/main.rs index 0963188..5ca0bc6 100644 --- a/agent/src/main.rs +++ b/agent/src/main.rs @@ -3,7 +3,7 @@ use agent_lib::{ }; use anyhow::{anyhow, Result}; use clap::Parser; -use log::{debug, error, info, trace}; +use log::{debug, info, trace}; #[derive(Parser)] #[clap( @@ -33,23 +33,13 @@ fn main() -> Result<()> { let mut external_api = ExternalApi::new(config.serial.path, config.serial.baud_rate); - let code_entry = external_api.read_from_serial()?; - let mut internal_api = InternalApi::new(code_entry); - internal_api.create_workspace()?; - let res = internal_api.run().map_err(|e| anyhow!("{:?}", e)); - - match res { - Err(e) => error!("Error: {:?}", e), - Ok(code) => { - info!("Code: {:?}", code); + external_api.send_status_message()?; - // Convert Code object to JSON - let code_json = serde_json::to_string(&code).unwrap(); - - // Write the JSON to the serial port - external_api.write_to_serial(&code_json)?; - } - } + let request_message = external_api.read_from_serial()?; + let mut internal_api = InternalApi::new(request_message); + internal_api.create_workspace()?; + let response_message = internal_api.run().map_err(|e| anyhow!("{:?}", e))?; + external_api.send_response_message(response_message)?; info!("Stopping agent"); Ok(())