From 0c449c47bcf69c60b5f165ad1fd976417da0c4c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iwo=20Strzebo=C5=84ski?= Date: Thu, 29 Oct 2026 16:20:03 +0000 Subject: [PATCH] Add a read-only dry run of a print's filament mapping bambu_mapping_check downloads one project from the card and prints the AMS mapping the production path would send, starting nothing. --- examples/bambu_mapping_check.rs | 55 +++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 examples/bambu_mapping_check.rs diff --git a/examples/bambu_mapping_check.rs b/examples/bambu_mapping_check.rs new file mode 100644 index 0000000..4b0d159 --- /dev/null +++ b/examples/bambu_mapping_check.rs @@ -0,0 +1,55 @@ +//! Run with: cargo run --example bambu_mapping_check -- +//! +//! **Read-only dry run of what a print would do.** Connects, reads the +//! printer's state and loaded filament, downloads one project from the SD +//! card root over FTPS, and prints the AMS mapping the production path would +//! send - without sending it. Starts nothing, uploads nothing, deletes +//! nothing. An optional third argument saves the downloaded copy locally. + +use std::time::Duration; + +use continuum_proxy::fleet; +use continuum_proxy::printer::{GenericPrinter, PrinterHandle}; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + let mut args = std::env::args().skip(1); + let (Some(target), Some(file)) = (args.next(), args.next()) else { + anyhow::bail!("usage: cargo run --example bambu_mapping_check -- [save-to]"); + }; + let save_to = args.next(); + + let mut printers = fleet::load(std::path::Path::new("printers.toml"))?; + let printer = printers + .iter_mut() + .find(|p| p.base().id == target) + .ok_or_else(|| anyhow::anyhow!("no printer with id '{target}' in printers.toml"))?; + let PrinterHandle::Bambu(bambu) = printer else { + anyhow::bail!("'{target}' is not a Bambu printer"); + }; + + tokio::time::timeout(Duration::from_secs(20), bambu.connect()) + .await + .map_err(|_| anyhow::anyhow!("connect timed out"))??; + bambu.pushall().await.ok(); + tokio::time::sleep(Duration::from_secs(4)).await; + + let report = bambu.print_status().await.ok_or_else(|| anyhow::anyhow!("no status yet"))?; + println!("gcode_state: {:?}", report.gcode_state); + println!("{:#?}", report.ams); + + let bytes = bambu.download_file(&format!("/{file}")).await?; + println!("downloaded {} bytes", bytes.len()); + if let Some(path) = save_to { + std::fs::write(&path, &bytes)?; + println!("saved a copy to {path}"); + } + for f in continuum_proxy::printer::plate_filaments(&bytes, 1)? { + println!("project filament {}: {} {} #{}", f.index, f.filament_type, f.tray_info_idx, f.color); + } + match bambu.filament_source_for(&bytes, 1).await { + Ok(source) => println!("mapping the production path would use: {source:?}"), + Err(err) => println!("the production path would REFUSE: {err}"), + } + Ok(()) +}