Make the filament source explicit, and print from the AMS
`start_uploaded_file` hardcoded `use_ams: false` / `ams_mapping: ""`, which silently overrode whatever the slicer had chosen. On a P1P with an AMS and a project sliced for it, that is not a missing feature - it points the print at the external spool. Confirmed on 2026-10-11: the print started, heated to 250C, reached 1%, then the printer paused itself with `print_error: 50364420` and `tray_now: 255`. Nothing in the command's reply said so; `result` was `success`, because the command had been accepted. So `FilamentSource` is now a required argument with no default, because there is no safe default - picking wrong draws the wrong filament or none. The `ExternalSpool` variant sends the empty *string* the schema's trailing `oneOf` demands, and `ams` takes slots per project filament index and pads to every tray the printer has, per the padding rule in `schemas/bambulab/v1/common/ams/ams_mapping.schema.json`. It refuses an empty mapping (padding `[]` would mean `use_ams: true` with nothing mapped), one longer than the printer has trays, and any negative that is not -1. Confirmed live with the real mapping: `ams_mapping: [3,-1,-1,-1,-1]`, `use_ams: true` took the printer to RUNNING, `tray_now` became 3 - the slot the project was sliced for - and it ran past 1% to 13% with `print_error: 0`, where the external-spool attempt had paused. Finding the mapping needed reading the project back off the card, so FTPS gains `download`/`download_file` and the probe a `fetch` step. The archive's `Metadata/slice_info.config` lists each plate's filaments with `tray_info_idx` and colour - here one PETG GFG99 at `#2850E0`, matching AMS slot 3's `2850E0FF` - and `Metadata/plate_1.gcode` is present, which also confirms the hardcoded `param`. `upload_project_file` is left on the external spool and is the one remaining place that can pick wrong, because it is vendor-generic and an AMS mapping is a Bambu concept. It is unreachable - there is no start-print command on the uplink - and the fix is for it to derive the mapping from the `.3mf` it already holds, which needs a zip reader and so a dependency decision. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -116,6 +116,42 @@ pub fn upload(
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
/// Blocking: reads one file off the printer's SD card.
|
||||
///
|
||||
/// Read-only. The reason this exists: a `.3mf` already on the card is the
|
||||
/// only record of which filament each of its plates was sliced for, and
|
||||
/// `ams_mapping` cannot be built without that - see
|
||||
/// `schemas/bambulab/v1/common/ams/ams_mapping.schema.json`. Printing a
|
||||
/// project with the wrong mapping is not a cosmetic error; it draws the
|
||||
/// wrong filament, or none.
|
||||
pub fn download(
|
||||
host: &str,
|
||||
access_code: &str,
|
||||
connector: native_tls::TlsConnector,
|
||||
path: &str,
|
||||
) -> anyhow::Result<Vec<u8>> {
|
||||
let mut ftp = NativeTlsFtpStream::connect_secure_implicit(
|
||||
(host, FTPS_PORT),
|
||||
NativeTlsConnector::from(connector),
|
||||
host,
|
||||
)?;
|
||||
|
||||
ftp.login(FTPS_USER, access_code)?;
|
||||
// A `.3mf` is a zip archive; letting the server treat it as text is free
|
||||
// corruption, exactly as on the way up.
|
||||
ftp.transfer_type(FileType::Binary)?;
|
||||
|
||||
// `retr_as_buffer` rather than `retr_as_stream`: suppaftp 12's
|
||||
// `TransferStream` finalizes itself on drop, and the files being read
|
||||
// here are project archives of a few hundred KB, so there is nothing to
|
||||
// gain from streaming them.
|
||||
let bytes = ftp.retr_as_buffer(path)?.into_inner();
|
||||
|
||||
let _ = ftp.quit();
|
||||
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
/// Blocking: lists `cache/` on the printer.
|
||||
///
|
||||
/// Read-only, and the counterpart to `upload`. The previous version of this
|
||||
|
||||
Reference in New Issue
Block a user