-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathuno_q_setup.rs
More file actions
143 lines (126 loc) · 4.79 KB
/
uno_q_setup.rs
File metadata and controls
143 lines (126 loc) · 4.79 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
//! Deploy Gloamy Bridge app to Arduino Uno Q.
use anyhow::{Context, Result};
use std::process::Command;
const BRIDGE_APP_NAME: &str = "gloamy-uno-q-bridge";
/// Deploy the Bridge app. If host is Some, scp from repo and ssh to start.
/// If host is None, assume we're ON the Uno Q — use embedded files and start.
pub fn setup_uno_q_bridge(host: Option<&str>) -> Result<()> {
let bridge_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("firmware")
.join("gloamy-uno-q-bridge");
if let Some(h) = host {
if bridge_dir.exists() {
deploy_remote(h, &bridge_dir)?;
} else {
anyhow::bail!(
"Bridge app not found at {}. Run from gloamy repo root.",
bridge_dir.display()
);
}
} else {
deploy_local(if bridge_dir.exists() {
Some(&bridge_dir)
} else {
None
})?;
}
Ok(())
}
fn deploy_remote(host: &str, bridge_dir: &std::path::Path) -> Result<()> {
let ssh_target = if host.contains('@') {
host.to_string()
} else {
format!("arduino@{}", host)
};
println!("Copying Bridge app to {}...", host);
let status = Command::new("ssh")
.args([&ssh_target, "mkdir", "-p", "~/ArduinoApps"])
.status()
.context("ssh mkdir failed")?;
if !status.success() {
anyhow::bail!("Failed to create ArduinoApps dir on Uno Q");
}
let status = Command::new("scp")
.args([
"-r",
bridge_dir.to_str().unwrap(),
&format!("{}:~/ArduinoApps/", ssh_target),
])
.status()
.context("scp failed")?;
if !status.success() {
anyhow::bail!("Failed to copy Bridge app");
}
println!("Starting Bridge app on Uno Q...");
let status = Command::new("ssh")
.args([
&ssh_target,
"arduino-app-cli",
"app",
"start",
"~/ArduinoApps/gloamy-uno-q-bridge",
])
.status()
.context("arduino-app-cli start failed")?;
if !status.success() {
anyhow::bail!("Failed to start Bridge app. Ensure arduino-app-cli is installed on Uno Q.");
}
println!("Gloamy Bridge app started. Add to config.toml:");
println!(" [[peripherals.boards]]");
println!(" board = \"arduino-uno-q\"");
println!(" transport = \"bridge\"");
Ok(())
}
fn deploy_local(bridge_dir: Option<&std::path::Path>) -> Result<()> {
let home = std::env::var("HOME").unwrap_or_else(|_| "/home/arduino".into());
let apps_dir = std::path::Path::new(&home).join("ArduinoApps");
let dest_dir = apps_dir.join(BRIDGE_APP_NAME);
std::fs::create_dir_all(&dest_dir).context("create dest dir")?;
if let Some(src) = bridge_dir {
println!("Copying Bridge app from repo...");
copy_dir(src, &dest_dir)?;
} else {
println!("Writing embedded Bridge app...");
write_embedded_bridge(&dest_dir)?;
}
println!("Starting Bridge app...");
let status = Command::new("arduino-app-cli")
.args(["app", "start", dest_dir.to_str().unwrap()])
.status()
.context("arduino-app-cli start failed")?;
if !status.success() {
anyhow::bail!("Failed to start Bridge app. Ensure arduino-app-cli is installed on Uno Q.");
}
println!("Gloamy Bridge app started.");
Ok(())
}
fn write_embedded_bridge(dest: &std::path::Path) -> Result<()> {
let app_yaml = include_str!("../../firmware/gloamy-uno-q-bridge/app.yaml");
let sketch_ino = include_str!("../../firmware/gloamy-uno-q-bridge/sketch/sketch.ino");
let sketch_yaml = include_str!("../../firmware/gloamy-uno-q-bridge/sketch/sketch.yaml");
let main_py = include_str!("../../firmware/gloamy-uno-q-bridge/python/main.py");
let requirements = include_str!("../../firmware/gloamy-uno-q-bridge/python/requirements.txt");
std::fs::write(dest.join("app.yaml"), app_yaml)?;
std::fs::create_dir_all(dest.join("sketch"))?;
std::fs::write(dest.join("sketch").join("sketch.ino"), sketch_ino)?;
std::fs::write(dest.join("sketch").join("sketch.yaml"), sketch_yaml)?;
std::fs::create_dir_all(dest.join("python"))?;
std::fs::write(dest.join("python").join("main.py"), main_py)?;
std::fs::write(dest.join("python").join("requirements.txt"), requirements)?;
Ok(())
}
fn copy_dir(src: &std::path::Path, dst: &std::path::Path) -> Result<()> {
for entry in std::fs::read_dir(src)? {
let e = entry?;
let name = e.file_name();
let src_path = src.join(&name);
let dst_path = dst.join(&name);
if e.file_type()?.is_dir() {
std::fs::create_dir_all(&dst_path)?;
copy_dir(&src_path, &dst_path)?;
} else {
std::fs::copy(&src_path, &dst_path)?;
}
}
Ok(())
}