Add print.rs (AmsState/AmsUnit/AmsTray/XcamSettings), fix print vs pushing
Mirrors continuum-schemas' schemas/bambulab/ restructuring: PushallResponse removed (it never existed on the wire — pushall's request goes to "pushing", but the state-push stream it triggers arrives under "print", a different root key, not a direct reply). BambuReport::Pushing(...) -> BambuReport::Print(PrintReport). AmsTray is an untagged enum (Empty/Loaded) rather than one struct full of Option<T> fields, matching the JSON Schema's oneOf for the same slot - #[serde(deny_unknown_fields)] on EmptyTray is load-bearing: untagged enums try variants in order, and a loaded tray (superset of Empty's one field) would otherwise incorrectly match Empty first. Verified against the full real ams/xcam example from the conversation via examples/bambu_commands_demo.rs - both the empty and loaded tray in that payload deserialize to the correct enum variant.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
//! The ongoing print-state push (root key "print"). Doesn't carry a
|
||||
//! `CommandEnvelope` — no `sequence_id`/`command` seen on this one in the
|
||||
//! real capture, and it may genuinely not have them (an async push, not a
|
||||
//! reply to a specific request) — revisit if a real capture proves
|
||||
//! otherwise.
|
||||
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
pub struct PrintReport {
|
||||
pub ams: Option<AmsState>,
|
||||
pub ams_exist_bits: Option<String>,
|
||||
pub insert_flag: Option<bool>,
|
||||
pub power_on_flag: Option<bool>,
|
||||
pub tray_exist_bits: Option<String>,
|
||||
pub tray_is_bbl_bits: Option<String>,
|
||||
pub xcam: Option<XcamSettings>,
|
||||
pub xcam_status: Option<String>,
|
||||
// The real payload has a lot more fields than shown here (this
|
||||
// example was truncated) — add them the same way, one field per line,
|
||||
// `Option<T>` for anything that isn't always present.
|
||||
}
|
||||
|
||||
/// Bambu's own naming has the outer container and the inner array both
|
||||
/// called `ams` — `print.ams.ams`, not a typo here, just what the printer
|
||||
/// actually sends.
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
pub struct AmsState {
|
||||
pub ams: Vec<AmsUnit>,
|
||||
}
|
||||
|
||||
/// One physical AMS unit (Bambu's numbering starts at 0 via `id`).
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
pub struct AmsUnit {
|
||||
pub humidity: String,
|
||||
pub id: String,
|
||||
pub temp: String,
|
||||
pub tray: Vec<AmsTray>,
|
||||
}
|
||||
|
||||
/// A tray slot is either empty (just `id`) or loaded (the full field set)
|
||||
/// — two genuinely different shapes, not one shape with optional fields,
|
||||
/// so this is an untagged enum rather than a struct full of `Option<T>`.
|
||||
/// `#[serde(deny_unknown_fields)]` on `Empty` is load-bearing: untagged
|
||||
/// enums try variants in order, and without it a *loaded* tray (which has
|
||||
/// every field `Empty` allows, plus more) would incorrectly match `Empty`
|
||||
/// first, since a plain struct doesn't reject extra fields by default.
|
||||
/// Verified this the hard way — see git history.
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
#[serde(untagged)]
|
||||
pub enum AmsTray {
|
||||
Empty(EmptyTray),
|
||||
Loaded(LoadedTray),
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct EmptyTray {
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
pub struct LoadedTray {
|
||||
pub id: String,
|
||||
pub bed_temp: String,
|
||||
pub bed_temp_type: String,
|
||||
pub cols: Vec<String>,
|
||||
pub drying_temp: String,
|
||||
pub drying_time: String,
|
||||
pub nozzle_temp_max: String,
|
||||
pub nozzle_temp_min: String,
|
||||
pub remain: i32,
|
||||
pub tag_uid: String,
|
||||
pub tray_color: String,
|
||||
pub tray_diameter: String,
|
||||
pub tray_id_name: String,
|
||||
pub tray_info_idx: String,
|
||||
pub tray_sub_brands: String,
|
||||
pub tray_type: String,
|
||||
pub tray_uuid: String,
|
||||
pub tray_weight: String,
|
||||
pub xcam_info: String,
|
||||
}
|
||||
|
||||
/// Camera-based AI print monitoring settings (spaghetti detection,
|
||||
/// first-layer inspection, etc.).
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
pub struct XcamSettings {
|
||||
pub allow_skip_parts: bool,
|
||||
pub buildplate_marker_detector: bool,
|
||||
pub first_layer_inspector: bool,
|
||||
pub halt_print_sensitivity: String,
|
||||
pub print_halt: bool,
|
||||
pub printing_monitor: bool,
|
||||
pub spaghetti_detector: bool,
|
||||
}
|
||||
Reference in New Issue
Block a user