Skip to content

Commit

Permalink
docs: internal_api & main
Browse files Browse the repository at this point in the history
Signed-off-by: Alexis-Bernard <[email protected]>

fix: deleted files are back

Signed-off-by: WoodenMaiden <[email protected]>
  • Loading branch information
alexis-ascoz authored and WoodenMaiden committed Apr 12, 2023
1 parent 8609280 commit 1a0fcaf
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 30 deletions.
66 changes: 66 additions & 0 deletions agent/lib/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::{
fs::File,
io::{self, BufReader},
};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum AgentConfigError {
#[error("cannot load config file")]
Load(#[from] io::Error),
#[error("cannot parse config file")]
Parse(#[from] serde_yaml::Error),
#[error("unsupported config kind")]
KindNotSupported,
#[error("unsupported config api version")]
VersionNotSupported,
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[allow(non_snake_case)]
pub struct AgentConfig {
/// The api version of the agent config file
pub apiVersion: String,
/// The kind of the agent config file
pub kind: String,
/// The serial configuration
pub serial: SerialConfig,
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
pub struct SerialConfig {
/// The path to the serial port
pub path: String,
/// The baud rate to use for the serial port
pub baud_rate: u32,
}

impl AgentConfig {
/// Load a AgentConfig from a file.
///
/// Arguments:
///
/// * `path`: The path to the config file.
///
/// Returns:
///
/// A Result<AgentConfig>
pub fn load(path: &str) -> Result<Self> {
let file = File::open(path).map_err(AgentConfigError::Load)?;
let reader = BufReader::new(file);
let config: AgentConfig =
serde_yaml::from_reader(reader).map_err(AgentConfigError::Parse)?;

if config.kind != "AgentConfig" {
return Err(AgentConfigError::KindNotSupported.into());
}

if config.apiVersion != "lambdo.io/v1alpha1" {
return Err(AgentConfigError::VersionNotSupported.into());
}

Ok(config)
}
}
64 changes: 64 additions & 0 deletions agent/lib/src/external_api/comms.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// This message is sent to the API server to indicate wether
// the agent is ready or not to receive messages.

pub const MESSAGE_SIZE_NB_BYTES: usize = 8;

pub struct Message {
pub message_size: [u8; MESSAGE_SIZE_NB_BYTES], // These are characters e.g. 00002048
pub message: Vec<u8> // stringified json, vec because size is unknown
}

impl Message {
pub fn new(message_to_send: String) -> Self {
let mut message_size = [0; MESSAGE_SIZE_NB_BYTES];
let message = message_to_send.as_bytes().to_vec();

let string_size = format!("{:0>8}", message.len());
//We can't call directly as bytes as both &str and String sizes are not known at
//compile time unlike message_size

for (i, c) in string_size.chars().enumerate() {
message_size[i] = c as u8;
}

Self {
message_size,
message
}
}

pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.extend_from_slice(&self.message_size);
bytes.extend_from_slice(&self.message);
bytes
}


}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn new_message_well_encoded() {
let message_data = "Hello world".to_string();
let message = Message::new(message_data);
assert_eq!(message.message, [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]);
assert_eq!(message.message_size, [48, 48, 48, 48, 48, 48, 49, 49]);

assert_eq!(message.to_bytes(), [48, 48, 48, 48, 48, 48, 49, 49, 72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]);
}


#[test]
fn message_size_badly_encoded() {
let message_data = "Hello world".to_string();
let message = Message::new(message_data);
assert_eq!(message.message, [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]);
assert_ne!(message.message_size, [48, 48, 48, 48, 48, 48, 49, 50]); // should be 11, is 12
}

}

62 changes: 32 additions & 30 deletions agent/lib/src/external_api/service.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
use anyhow::{anyhow, Result};
use log::{error, info, debug, trace};
use log::{debug, error, info, trace};

use serialport::SerialPort;

use super::model::{RequestMessage, ResponseMessage, StatusMessage};
use super::comms::{Message, MESSAGE_SIZE_NB_BYTES};
use super::model::{RequestMessage, ResponseMessage, StatusMessage};

pub struct ExternalApi {
serial_path: String,
serial_baud_rate: u32,

serial_port: Box<dyn SerialPort>, // So we don't open it multiple times
}

impl ExternalApi {
pub fn new(serial_path: String, serial_baud_rate: u32) -> Self {
Self {
serial_path,
serial_path: serial_path.clone(),
serial_baud_rate,
serial_port: serialport::new(serial_path, serial_baud_rate)
.open()
.unwrap(),
}
}

pub fn read_from_serial(&mut self) -> Result<RequestMessage> {
info!("Reading from serial port: {}", self.serial_path);

// Open the serial port
let mut serial = serialport::new(&self.serial_path, self.serial_baud_rate)
.open()
.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];
Expand All @@ -36,9 +38,9 @@ impl ExternalApi {
// Create the final vector to hold the data
let mut data_received: Vec<u8> = Vec::new();

//we read the buffer and retrieve the first 8 bytes which are the size of the message
//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) {
match self.serial_port.read(&mut size_buffer) {
Ok(t) => {
if t == 0 {
break;
Expand All @@ -52,18 +54,15 @@ impl ExternalApi {

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)
)?;


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::<usize>().map_err(
|e| anyhow!("Failed to parse length of message: {}", e)
)?;

data_size = size_string
.parse::<usize>()
.map_err(|e| anyhow!("Failed to parse length of message: {}", e))?;

data_received.drain(..MESSAGE_SIZE_NB_BYTES);
}
Expand All @@ -76,7 +75,7 @@ impl ExternalApi {
bytes_read = 0;

while bytes_read < data_size {
match serial.read(&mut buf) {
match self.serial_port.read(&mut buf) {
Ok(t) => {
if t > 0 {
bytes_read += t;
Expand All @@ -97,7 +96,7 @@ impl ExternalApi {
info!("Code entry: {:?}", code_entry);

// Flush the serial port
serial
self.serial_port
.flush()
.map_err(|e| anyhow!("Failed to flush serial port: {}", e))?;

Expand Down Expand Up @@ -137,22 +136,25 @@ impl ExternalApi {
}

pub fn write_to_serial(&mut self, data: &str) -> Result<()> {
// Open the serial port
let mut serial = serialport::new(&self.serial_path, self.serial_baud_rate)
.open()
.map_err(|e| anyhow!("Failed to open serial port: {}", e))?;
info!("Writing to serial port: {}", self.serial_path);

// Conver the string to a byte array
// Convert the string to a byte array
let message = Message::new(data.to_string()).to_bytes();
let buf = message.as_slice();

// Write the byte array to the serial port
serial
self.serial_port
.write_all(buf)
.map_err(|e| anyhow!("Failed to write to serial port: {}", e))?;

// In order to still be readable by ``readline`` on the other side, we add a carriage return
// (not included in the message size)
self.serial_port
.write("\r\n".as_bytes())
.map_err(|e| anyhow!("Failed to write to serial port: {}", e))?;

// Flush the serial port
serial
self.serial_port
.flush()
.map_err(|e| anyhow!("Failed to flush serial port: {}", e))?;
Ok(())
Expand Down
2 changes: 2 additions & 0 deletions agent/lib/src/internal_api/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod model;
pub mod service;
14 changes: 14 additions & 0 deletions agent/lib/src/internal_api/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ use std::path::PathBuf;

use serde::{Deserialize, Serialize};

/// A struct to represent a file in the request message
///
/// # Attributes
///
/// * `path` - The path of the file
/// * `file_name` - The name of the file
/// * `content` - The content of the file
#[derive(Deserialize, Serialize, Debug)]
pub struct FileModel {
pub path: PathBuf,
Expand All @@ -19,6 +26,13 @@ impl FileModel {
}
}

/// A struct to represent the result of a command
///
/// # Attributes
///
/// * `stdout` - The stdout of the command
/// * `stderr` - The stderr of the command
/// * `exit_code` - The exit code of the command
#[derive(Deserialize, Serialize, Debug)]
pub struct CodeReturn {
pub stdout: String,
Expand Down
Loading

0 comments on commit 1a0fcaf

Please sign in to comment.