Add upload_project_file/send_gcode_line, real Marlin serial, Bambu protocol auto-detect

- GenericPrinter grows upload_project_file, send_gcode_line, and a
  generic upload_gcode<P> driver that streams a whole gcode file line by
  line through any vendor's send_gcode_line.
- PrusaSerialPrinter's connect/send_gcode_line are real (not stubs): a
  held-open MarlinSerialConnection (src/printer/marlin_serial.rs) writes
  each line and waits for Marlin's "ok" before sending the next. Config
  changed from com_port: i16 to port: String + baud_rate: u32 to hold a
  real device path.
- Bambu: BambuGenericPrinter + BambuV1Printer/BambuV2Printer collapsed
  into one BambuPrinter, since which MQTT/BambuMQTT version (v3.1.1/v1
  vs v5/v2) a printer speaks is discovered at connect() time (or forced),
  not something config should pick a type for - the same physical
  printer can change after a firmware update. printers.toml gets a new
  "bambu" vendor (auto-detect, the default) alongside bambu_v1/bambu_v2
  (force a specific one).
- Bambu's gcode_line request is now built for real via
  continuum-schema-instance against continuum-schemas' JSON Schema,
  picking the v1 or v2 schema directory based on the detected protocol
  version, instead of a hand-written serde struct.
- Added rumqttc as a dependency (not wired up yet - the real MQTT
  v5-then-v3.1.1 fallback connect and the publish/receive plumbing are
  still stubs).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MWQVtBGxHYLkVw2kBupd5g
This commit is contained in:
2026-09-05 20:40:21 +00:00
co-authored by Claude Sonnet 5
parent a2d4e578ec
commit 2c4ef21291
13 changed files with 559 additions and 203 deletions
+15 -15
View File
@@ -4,36 +4,40 @@
//! - `connect()` is called the same way regardless of vendor (polymorphism),
//! but each variant's `impl GenericPrinter` runs completely different
//! code (override).
//! - `dispatch_gcode()` only exists on the two Bambu structs (extension) -
//! you have to `match` the enum back down to the concrete type to reach
//! it, which is the trade-off for not having implicit downcasting.
//! - `dispatch_gcode()` only exists on the Bambu struct (extension) - you
//! have to `match` the enum back down to the concrete type to reach it,
//! which is the trade-off for not having implicit downcasting.
use continuum_proxy::printer::{
BambuTls, BambuV1Printer, BambuV2Printer, GenericPrinter, KlipperPrinter, PrinterHandle, PrusaLinkPrinter,
PrusaSerialPrinter,
BambuPrinter, BambuProtocolPreference, BambuTls, GenericPrinter, KlipperPrinter, PrinterHandle,
PrusaLinkPrinter, PrusaSerialPrinter,
};
#[tokio::main]
async fn main() {
let mut fleet: Vec<PrinterHandle> = vec![
PrinterHandle::BambuV1(BambuV1Printer::new(
// Forced: a known-old printer.
PrinterHandle::Bambu(BambuPrinter::new(
"p1",
"P1S",
"192.168.1.49",
"87654321",
"01P00A000000000",
BambuTls::BundledCa,
BambuProtocolPreference::ForceV1,
)),
PrinterHandle::BambuV2(BambuV2Printer::new(
// Auto: the recommended default - see bambu.rs's doc comment.
PrinterHandle::Bambu(BambuPrinter::new(
"p2",
"X1 Carbon",
"192.168.1.50",
"12345678",
"00M00A000000000",
BambuTls::BundledCa,
BambuProtocolPreference::Auto,
)),
PrinterHandle::PrusaLink(PrusaLinkPrinter::new("p3", "MK4", "192.168.1.51", "prusa-api-key")),
PrinterHandle::PrusaSerial(PrusaSerialPrinter::new("p4", "MK3S+", 0)),
PrinterHandle::PrusaSerial(PrusaSerialPrinter::new("p4", "MK3S+", "/dev/ttyACM0", 115_200)),
PrinterHandle::Klipper(KlipperPrinter::new("p5", "Voron 2.4", "192.168.1.52")),
// No host configured - this one will hit the Err path.
PrinterHandle::Klipper(KlipperPrinter::new("p6", "Broken Voron", "")),
@@ -50,15 +54,11 @@ async fn main() {
}
// Vendor-only extension: reachable only after matching the concrete
// variant back out of the enum. BambuV1Printer and BambuV2Printer are
// separate types now (each *has* a BambuGenericPrinter rather than
// being the same struct), so - unlike before the split - this needs
// two arms instead of one `A(x) | B(x)` pattern: an or-pattern requires
// every alternative to bind the same type, and these no longer do.
// variant back out of the enum - one arm now that Bambu is a single
// type regardless of which protocol version `connect()` settled on.
for printer in &fleet {
match printer {
PrinterHandle::BambuV1(bambu) => bambu.dispatch_gcode("part.gcode.3mf"),
PrinterHandle::BambuV2(bambu) => bambu.dispatch_gcode("part.gcode.3mf"),
PrinterHandle::Bambu(bambu) => bambu.dispatch_gcode("part.gcode.3mf"),
_ => {}
}
}