-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy patharduino_flash.rs
More file actions
145 lines (123 loc) · 4.99 KB
/
arduino_flash.rs
File metadata and controls
145 lines (123 loc) · 4.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//! Flash Gloamy Arduino firmware via arduino-cli.
//!
//! Ensures arduino-cli is available (installs via brew on macOS if missing),
//! installs the AVR core, compiles and uploads the base firmware.
use anyhow::{Context, Result};
use std::process::Command;
/// Gloamy Arduino Uno base firmware (capabilities, gpio_read, gpio_write).
const FIRMWARE_INO: &str = include_str!("../../firmware/gloamy-arduino/gloamy-arduino.ino");
const FQBN: &str = "arduino:avr:uno";
const SKETCH_NAME: &str = "gloamy-arduino";
/// Check if arduino-cli is available.
pub fn arduino_cli_available() -> bool {
Command::new("arduino-cli")
.arg("version")
.output()
.map(|o| o.status.success())
.unwrap_or(false)
}
/// Try to install arduino-cli. Returns Ok(()) if installed or already present.
pub fn ensure_arduino_cli() -> Result<()> {
if arduino_cli_available() {
return Ok(());
}
#[cfg(target_os = "macos")]
{
println!("arduino-cli not found. Installing via Homebrew...");
let status = Command::new("brew")
.args(["install", "arduino-cli"])
.status()
.context("Failed to run brew install")?;
if !status.success() {
anyhow::bail!("brew install arduino-cli failed. Install manually: https://arduino.github.io/arduino-cli/");
}
println!("arduino-cli installed.");
if !arduino_cli_available() {
anyhow::bail!("arduino-cli still not found after install. Ensure it's in PATH.");
}
}
#[cfg(target_os = "linux")]
{
println!("arduino-cli not found. Run the install script:");
println!(" curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh");
println!();
println!("Or install via package manager (e.g. apt install arduino-cli on Debian/Ubuntu).");
anyhow::bail!("arduino-cli not installed. Install it and try again.");
}
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
{
println!("arduino-cli not found. Install it: https://arduino.github.io/arduino-cli/");
anyhow::bail!("arduino-cli not installed.");
}
#[allow(unreachable_code)]
Ok(())
}
/// Ensure arduino:avr core is installed.
fn ensure_avr_core() -> Result<()> {
let out = Command::new("arduino-cli")
.args(["core", "list"])
.output()
.context("arduino-cli core list failed")?;
let stdout = String::from_utf8_lossy(&out.stdout);
if stdout.contains("arduino:avr") {
return Ok(());
}
println!("Installing Arduino AVR core...");
let status = Command::new("arduino-cli")
.args(["core", "install", "arduino:avr"])
.status()
.context("arduino-cli core install failed")?;
if !status.success() {
anyhow::bail!("Failed to install arduino:avr core");
}
println!("AVR core installed.");
Ok(())
}
/// Flash Gloamy firmware to Arduino at the given port.
pub fn flash_arduino_firmware(port: &str) -> Result<()> {
ensure_arduino_cli()?;
ensure_avr_core()?;
let temp_dir = std::env::temp_dir().join(format!("gloamy_flash_{}", uuid::Uuid::new_v4()));
let sketch_dir = temp_dir.join(SKETCH_NAME);
let ino_path = sketch_dir.join(format!("{}.ino", SKETCH_NAME));
std::fs::create_dir_all(&sketch_dir).context("Failed to create sketch dir")?;
std::fs::write(&ino_path, FIRMWARE_INO).context("Failed to write firmware")?;
let sketch_path = sketch_dir.to_string_lossy();
// Compile
println!("Compiling Gloamy Arduino firmware...");
let compile = Command::new("arduino-cli")
.args(["compile", "--fqbn", FQBN, &*sketch_path])
.output()
.context("arduino-cli compile failed")?;
if !compile.status.success() {
let stderr = String::from_utf8_lossy(&compile.stderr);
let _ = std::fs::remove_dir_all(&temp_dir);
anyhow::bail!("Compile failed:\n{}", stderr);
}
// Upload
println!("Uploading to {}...", port);
let upload = Command::new("arduino-cli")
.args(["upload", "-p", port, "--fqbn", FQBN, &*sketch_path])
.output()
.context("arduino-cli upload failed")?;
let _ = std::fs::remove_dir_all(&temp_dir);
if !upload.status.success() {
let stderr = String::from_utf8_lossy(&upload.stderr);
anyhow::bail!("Upload failed:\n{}\n\nEnsure the board is connected and the port is correct (e.g. /dev/cu.usbmodem* on macOS).", stderr);
}
println!("Gloamy firmware flashed successfully.");
println!("The Arduino now supports: capabilities, gpio_read, gpio_write.");
Ok(())
}
/// Resolve port from config or path. Returns the path to use for flashing.
pub fn resolve_port(config: &crate::config::Config, path_override: Option<&str>) -> Option<String> {
if let Some(p) = path_override {
return Some(p.to_string());
}
config
.peripherals
.boards
.iter()
.find(|b| b.board == "arduino-uno" && b.transport == "serial")
.and_then(|b| b.path.clone())
}