use tloop_arduino as arduino;
pub mod commands;
mod state;
use tauri::Manager;
pub use state::LoopState;
pub use tloop_config::{Board, FirmwareConfig, LoopConfig, SerialConfig};
pub use commands::boards::BoardInfo;
pub use commands::serial::SerialLine;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum LoopFeature {
Flash,
SerialRead,
SerialPorts,
ConnectedBoards,
FileUpload,
}
pub struct Builder {
pub features: std::collections::HashSet<LoopFeature>,
pub boards: Vec<tloop_config::Board>,
pub firmware_sketch: Option<String>,
pub serial_baudrate: u32,
pub libraries: Vec<String>,
pub env_defaults: std::collections::HashMap<String, serde_json::Value>,
}
impl Builder {
pub fn new() -> Self {
Self {
features: std::collections::HashSet::new(),
boards: vec![],
firmware_sketch: None,
serial_baudrate: 9600,
libraries: vec![],
env_defaults: std::collections::HashMap::new(),
}
}
pub fn with_flash(mut self) -> Self {
self.features.insert(LoopFeature::Flash);
self
}
pub fn with_serial_read(mut self) -> Self {
self.features.insert(LoopFeature::SerialRead);
self
}
pub fn with_serial_ports(mut self) -> Self {
self.features.insert(LoopFeature::SerialPorts);
self
}
pub fn with_connected_boards(mut self) -> Self {
self.features.insert(LoopFeature::ConnectedBoards);
self
}
pub fn with_file_upload(mut self) -> Self {
self.features.insert(LoopFeature::FileUpload);
self
}
pub fn with_boards(mut self, boards: Vec<tloop_config::Board>) -> Self {
self.boards = boards;
self
}
pub fn with_firmware_sketch(mut self, path: String) -> Self {
self.firmware_sketch = Some(path);
self
}
pub fn with_libraries(mut self, libs: Vec<String>) -> Self {
self.libraries = libs;
self
}
pub fn with_serial_baudrate(mut self, baud: u32) -> Self {
self.serial_baudrate = baud;
self
}
pub fn with_env_defaults(mut self, defaults: std::collections::HashMap<String, serde_json::Value>) -> Self {
self.env_defaults = defaults;
self
}
pub fn build(self) -> tauri::plugin::TauriPlugin<tauri::Wry> {
let features = self.features.clone();
let boards = self.boards.clone();
let firmware_sketch = self.firmware_sketch.clone();
let serial_baudrate = self.serial_baudrate;
let libraries = self.libraries.clone();
let env_defaults = self.env_defaults.clone();
tauri::plugin::Builder::new("loop")
.invoke_handler(tauri::generate_handler![
commands::env_vars::loop_set_env,
commands::env_vars::loop_get_env,
commands::serial::loop_serial_ports,
commands::serial::loop_serial_start,
commands::serial::loop_serial_stop,
commands::boards::loop_connected_boards,
commands::flash::loop_flash,
])
.setup(move |app, _| {
let arduino_cli = arduino::extract_arduino_cli(app.path().app_cache_dir()?)?;
let mut state = LoopState::new(arduino_cli, features.clone(), boards.clone());
state.firmware_sketch = firmware_sketch.clone();
state.serial_baudrate = serial_baudrate;
state.libraries = libraries.clone();
state.env_defaults = env_defaults.clone();
app.manage(state);
Ok(())
})
.build()
}
}
impl Default for Builder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn builder_tracks_features() {
let b = Builder::new().with_flash().with_serial_ports();
assert!(b.features.contains(&LoopFeature::Flash));
assert!(b.features.contains(&LoopFeature::SerialPorts));
assert!(!b.features.contains(&LoopFeature::SerialRead));
}
#[test]
fn builder_stores_boards() {
let board = tloop_config::Board {
name: "uno".into(),
fqbn: "arduino:avr:uno".into(),
url: None,
upload_speed: None,
};
let b = Builder::new().with_boards(vec![board]);
assert_eq!(b.boards.len(), 1);
assert_eq!(b.boards[0].name, "uno");
}
#[test]
fn builder_stores_env_defaults() {
let mut defaults = std::collections::HashMap::new();
defaults.insert("speed".into(), serde_json::json!(100));
let b = Builder::new().with_env_defaults(defaults);
assert_eq!(b.env_defaults.get("speed"), Some(&serde_json::json!(100)));
}
}