diff --git a/src/printer/bambu.rs b/src/printer/bambu.rs index e6fb4ad..7afc039 100644 --- a/src/printer/bambu.rs +++ b/src/printer/bambu.rs @@ -384,6 +384,7 @@ pub const CHAMBER_LIGHT: &str = "chamber_light"; /// So this is a required argument rather than an option with a default. /// There is no safe default: picking the wrong source draws the wrong /// filament or none at all. +#[derive(Debug, Clone, PartialEq, Eq)] pub enum FilamentSource { /// The external spool (`vt_tray`). `use_ams: false`, and /// `ams_mapping` must be the empty *string* - the schema's trailing @@ -1090,6 +1091,20 @@ impl BambuPrinter { /// - **`url` spelling.** `ftp:///` - empty host, triple slash, /// resolved against the card's root - is accepted. `file:///` was /// never needed and remains untested. + /// - **An accepted start is not a successful print, and the failure can + /// be physical.** Confirmed end to end on 2026-10-15 via + /// `upload_project_file`: the mapping derived correctly + /// (`ams_mapping` slot 3, and the printer echoed `tray_tar: 3`), the + /// upload matched byte for byte, the printer went + /// `IDLE -> PREPARE -> RUNNING`, heated to 255C - and then paused + /// itself at stage 54 with `print_error: 0x07008003` and + /// `hms: [{attr: 0x07002300, code: 0x00020004}]`, i.e. + /// `HMS_0700_2300_0002_0004`, which is a broken-filament fault on the + /// slot it was loading. Nothing in this code was wrong; the filament + /// was. Which is the point: `command_outcome` can only report what + /// the printer said about the *command*, so anything that wants to + /// know whether a print is actually running has to watch + /// `gcode_state`, `print_error` and `hms` afterwards. /// - **`use_ams: false` / `ams_mapping: ""`.** Accepted by the printer - /// and *wrong* on an AMS-equipped machine. Confirmed on a second run /// the same day, against a project the owner had sliced in Bambu @@ -1187,6 +1202,24 @@ impl BambuPrinter { // things. Unverified - see this method's doc comment, which // records what the hardware said about the `cache/` spelling. body["param"] = serde_json::Value::String(format!("/{file_name}")); + + // `filament` has nowhere to go here: `gcode_file` takes only + // `command` and `param` - no `use_ams`, no `ams_mapping` - so a + // bare gcode draws whatever its own tool changes select. That is + // correct, but it means this argument is silently discarded for + // half the inputs this method accepts, and "a filament choice + // quietly overridden" is precisely the bug `FilamentSource` was + // introduced to stop. So say so rather than letting a caller + // believe its mapping took effect. + if !matches!(filament, FilamentSource::ExternalSpool) { + tracing::warn!( + printer = %self.base.name, + file = file_name, + ?filament, + "ignoring the filament source: a bare .gcode has no use_ams/ams_mapping \ + field to put it in, so the gcode's own tool changes decide" + ); + } } // A correlated `request`, not a fire-and-forget publish. This was