Skip to main content

zeroclaw/peripherals/
mod.rs

1#[allow(unused_imports)]
2#[cfg(feature = "hardware")]
3pub use zeroclaw_hardware::peripherals::*;
4
5use crate::config::{Config, PeripheralBoardConfig};
6use anyhow::Result;
7
8pub async fn handle_command(cmd: crate::PeripheralCommands, config: &Config) -> Result<()> {
9    match cmd {
10        crate::PeripheralCommands::List => {
11            let boards: Vec<&PeripheralBoardConfig> = if config.peripherals.enabled {
12                config.peripherals.boards.iter().collect()
13            } else {
14                Vec::new()
15            };
16            if boards.is_empty() {
17                println!("No peripherals configured.");
18                println!();
19                println!("Add one with: zeroclaw peripheral add <board> <path>");
20                println!("  Example: zeroclaw peripheral add nucleo-f401re /dev/ttyACM0");
21                println!();
22                println!("Or add to config.toml:");
23                println!("  [peripherals]");
24                println!("  enabled = true");
25                println!();
26                println!("  [[peripherals.boards]]");
27                println!("  board = \"nucleo-f401re\"");
28                println!("  transport = \"serial\"");
29                println!("  path = \"/dev/ttyACM0\"");
30            } else {
31                println!("Configured peripherals:");
32                for b in boards {
33                    let path = b.path.as_deref().unwrap_or("(native)");
34                    println!("  {}  {}  {}", b.board, b.transport, path);
35                }
36            }
37        }
38        crate::PeripheralCommands::Add { board, path } => {
39            let transport = if path == "native" { "native" } else { "serial" };
40            let path_opt = if path == "native" {
41                None
42            } else {
43                Some(path.clone())
44            };
45
46            let mut cfg = Box::pin(crate::config::Config::load_or_init()).await?;
47            cfg.peripherals.enabled = true;
48
49            if cfg
50                .peripherals
51                .boards
52                .iter()
53                .any(|b| b.board == board && b.path.as_deref() == path_opt.as_deref())
54            {
55                println!("Board {} at {:?} already configured.", board, path_opt);
56                return Ok(());
57            }
58
59            cfg.peripherals.boards.push(PeripheralBoardConfig {
60                board: board.clone(),
61                transport: transport.to_string(),
62                path: path_opt,
63                baud: 115_200,
64            });
65            Box::pin(cfg.save()).await?;
66            println!("Added {} at {}. Restart daemon to apply.", board, path);
67        }
68        #[cfg(feature = "hardware")]
69        crate::PeripheralCommands::Flash { port } => {
70            let port_str = arduino_flash::resolve_port(config, port.as_deref())
71                .or_else(|| port.clone())
72                .ok_or_else(|| {
73                    ::zeroclaw_log::record!(
74                        WARN,
75                        ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)
76                            .with_outcome(::zeroclaw_log::EventOutcome::Failure),
77                        "peripheral flash refused: no port resolved (no --port flag and no arduino-uno in config)"
78                    );
79                    anyhow::Error::msg(
80                        "No port specified. Use --port /dev/cu.usbmodem* or add arduino-uno to config.toml"
81                    )
82                })?;
83            arduino_flash::flash_arduino_firmware(&port_str)?;
84        }
85        #[cfg(not(feature = "hardware"))]
86        crate::PeripheralCommands::Flash { .. } => {
87            println!("Arduino flash requires the 'hardware' feature.");
88            println!("Build with: cargo build --features hardware");
89        }
90        #[cfg(feature = "hardware")]
91        crate::PeripheralCommands::SetupUnoQ { host } => {
92            uno_q_setup::setup_uno_q_bridge(host.as_deref())?;
93        }
94        #[cfg(not(feature = "hardware"))]
95        crate::PeripheralCommands::SetupUnoQ { .. } => {
96            println!("Uno Q setup requires the 'hardware' feature.");
97            println!("Build with: cargo build --features hardware");
98        }
99        #[cfg(feature = "hardware")]
100        crate::PeripheralCommands::FlashNucleo => {
101            nucleo_flash::flash_nucleo_firmware()?;
102        }
103        #[cfg(not(feature = "hardware"))]
104        crate::PeripheralCommands::FlashNucleo => {
105            println!("Nucleo flash requires the 'hardware' feature.");
106            println!("Build with: cargo build --features hardware");
107        }
108    }
109    Ok(())
110}