From 8e5d85202fbed4cd0e5c149521dfc30a0daf20af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iwo=20Strzebo=C5=84ski?= Date: Fri, 28 Aug 2026 22:41:55 +0000 Subject: [PATCH] Wire InfoCommand through as one real, runnable example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BambuRequest::Info(InfoCommand) is now live (was commented out) — examples/bambu_protocol_demo.rs constructs one, serializes it, and prints it next to Bambu's real wire JSON for comparison. Run it and copy this exact shape (proto message -> use it here -> add an enum variant) for every other command. --- Cargo.toml | 7 +++++ examples/bambu_protocol_demo.rs | 24 ++++++++++++++++ src/printer/bambu_protocol.rs | 50 +++++++++++++++++++++++++++++++++ src/printer/mod.rs | 2 ++ 4 files changed, 83 insertions(+) create mode 100644 examples/bambu_protocol_demo.rs create mode 100644 src/printer/bambu_protocol.rs diff --git a/Cargo.toml b/Cargo.toml index 2fb7276..43ca50f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,10 @@ path = "examples/fetch_bambu_cert.rs" name = "auto_connect_bambu" path = "examples/auto_connect_bambu.rs" +[[example]] +name = "bambu_protocol_demo" +path = "examples/bambu_protocol_demo.rs" + [dependencies] tokio = { version = "1.40", features = ["full"] } tokio-tungstenite = { version = "0.24", features = ["native-tls"] } @@ -47,3 +51,6 @@ dotenvy = "0.15" # Real printer protocol clients (MQTT for Bambu, HTTP for PrusaLink/ # Moonraker, FTPS for gcode transfer) go here once you're ready to build # past the stubs in src/printer/ — see that module's doc comment. +continuum-rust-types = { path = "../continuum-schemas/packages/rust-types" } +# FOR NON-LOCAL DEV +# continuum-rust-types = { git = "https://git.octoturge.com/Continuum/continuum-schemas.git" } diff --git a/examples/bambu_protocol_demo.rs b/examples/bambu_protocol_demo.rs new file mode 100644 index 0000000..4a37bd9 --- /dev/null +++ b/examples/bambu_protocol_demo.rs @@ -0,0 +1,24 @@ +//! Run with: cargo run --example bambu_protocol_demo +//! +//! Proves the whole pipeline end to end: a message written in +//! continuum-schemas' proto/bambulab/v1/request.proto, compiled by prost +//! into a real Rust struct, wrapped in the hand-written BambuRequest enum, +//! and serialized by plain serde — no protobuf binary encoding involved, +//! since Bambu's actual wire format is JSON over MQTT. + +use continuum_proxy::printer::BambuRequest; +use continuum_types::bambulab::v1::InfoCommand; + +fn main() { + let request = BambuRequest::Info(InfoCommand { + sequence_id: "0".to_string(), + command: "get_version".to_string(), + }); + + let actual = serde_json::to_string(&request).unwrap(); + let expected = r#"{"info":{"sequence_id":"0","command":"get_version"}}"#; + + println!("generated: {actual}"); + println!("Bambu's real wire format: {expected}"); + println!("match: {}", actual == expected); +} diff --git a/src/printer/bambu_protocol.rs b/src/printer/bambu_protocol.rs new file mode 100644 index 0000000..284dc45 --- /dev/null +++ b/src/printer/bambu_protocol.rs @@ -0,0 +1,50 @@ +//! Bambu's real MQTT wire format: `{"info": {...}}`, `{"pushing": {...}}`, +//! `{"print": {...}}` — one JSON object with a single key naming which +//! command/report it is. +//! +//! Deliberately NOT modeled as a proto `oneof` for the top level — see the +//! long comment in continuum-schemas/packages/rust-types/build.rs for why +//! (short version: prost-build's field/variant attribute matching can't +//! keep "the oneof field" and "the variants inside it" apart, so +//! `#[serde(flatten)]` can't be scoped correctly and won't compile). This +//! plain Rust enum sidesteps the problem entirely: serde's *default* enum +//! representation already produces exactly `{"info": {...}}` with zero +//! attributes needed. +//! +//! `Info` below is the one fully-wired example — run +//! `cargo run --example bambu_protocol_demo` to see it actually produce +//! Bambu's real wire JSON. Copy this exact shape for every other command: +//! 1. Write the message in continuum-schemas' bambulab/v1/request.proto +//! (or report.proto for a response). +//! 2. `use` it up top, same as `InfoCommand` below. +//! 3. Add one variant here, named to match Bambu's JSON key exactly +//! (`#[serde(rename_all = "snake_case")]` on the enum handles simple +//! cases automatically — a Rust variant `Pushing` becomes JSON key +//! `"pushing"` for free; only reach for `#[serde(rename = "...")]` on +//! a specific variant if the key doesn't snake_case cleanly from the +//! Rust name). + +use continuum_types::bambulab::v1::InfoCommand; + +/// One request you can send to a Bambu printer. Grows by one variant per +/// message you define in bambulab/v1/request.proto. +#[derive(serde::Serialize, Debug)] +#[serde(rename_all = "snake_case")] +pub enum BambuRequest { + Info(InfoCommand), + // Pushing(PushingCommand), +} + +/// One report/response received from a Bambu printer. Same idea, the other +/// direction — grows by one variant per message in bambulab/v1/report.proto. +/// Empty for now: no response messages defined yet (InfoResponse is the +/// natural first one — see the JSON example in bambu_protocol_demo.rs). +#[derive(serde::Deserialize, Debug)] +#[serde(rename_all = "snake_case")] +pub enum BambuReport {} + +// V1/V2 fork here once you know how much of the wire format actually +// differs: if it's mostly the same shape, one BambuRequest/BambuReport +// covering fields from both packages may be enough (some variants simply +// unused on one generation); if the reports genuinely diverge, mirror this +// file as bambu_protocol_v2.rs against continuum_types::bambulab::v2. diff --git a/src/printer/mod.rs b/src/printer/mod.rs index 0d6d1ac..f806d0a 100644 --- a/src/printer/mod.rs +++ b/src/printer/mod.rs @@ -29,10 +29,12 @@ //! `tokio::spawn`, not yet). mod bambu; +mod bambu_protocol; mod klipper; mod prusa; pub use bambu::{BambuGenericPrinter, BambuTls, BambuV1Printer, BambuV2Printer}; +pub use bambu_protocol::{BambuReport, BambuRequest}; pub use klipper::KlipperPrinter; pub use prusa::{PrusaLinkPrinter, PrusaSerialPrinter};