Fix broken $refs from the bambulab schema underscore-rename, remove stale v2/

- print.schema.json, _ams.schema.json, _ams_unit.schema.json still
  pointed at the pre-rename filenames (ams.schema.json, ams_unit.schema.json,
  ams_tray.schema.json) after the underscore-prefix split - fixed all
  three, verified with a full jsonschema + referencing validation run
  against real captures (get_version, pushall, a full print/ams/xcam
  report with both empty and loaded trays) plus negative tests.
- _upgrade_state.schema.json: fixed its $id (pointed at report/info/,
  file lives under report/print/) and its title (said "ModuleInfo",
  clearly copy-pasted from _module_info.schema.json). Wired it into
  print.schema.json as the print report's `upgrade_state` property -
  the file existed but nothing referenced it yet.
- Deleted schemas/bambulab/v2/, which had been recreated as stale,
  broken copies of an older v1 (missing the envelope allOf, missing
  the underscore renames, $ids still pointing at v1/ paths) - the
  repo's own README documents v2 as intentionally removed until V2's
  wire format is known to differ from V1's.
- Updated schemas/bambulab/README.md's layout tree and inheritance-
  example reference, both stale after the underscore rename.
- Removed stray tsc -b build output (packages/ts-types/src/*.d.ts/js)
  that isn't meant to be committed (outDir is dist/, gitignored).

Verified: cargo check clean (continuum-proxy, continuum-ai-worker,
rust-types), tsc clean (continuum-backend, continuum-common ts-core),
10/10 JSON Schema validation cases passing.
This commit is contained in:
2026-08-29 08:13:49 +00:00
parent cd18337e12
commit 4cc40c913c
20 changed files with 213 additions and 128 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
# continuum-schemas has no runtime it only emits generated types/structs. # continuum-schemas has no runtime - it only emits generated types/structs.
# This file is kept for consistency with the other Continuum repos. # This file is kept for consistency with the other Continuum repos.
# Optional: private registry token, only needed if packages/* are ever # Optional: private registry token, only needed if packages/* are ever
+2 -2
View File
@@ -3,11 +3,11 @@
Single source of truth for the Continuum data model. Protobuf definitions in Single source of truth for the Continuum data model. Protobuf definitions in
`proto/` are compiled into two consumer packages: `proto/` are compiled into two consumer packages:
- `packages/ts-types` TypeScript types generated via `ts-proto`, plus - `packages/ts-types` - TypeScript types generated via `ts-proto`, plus
hand-written [TypeBox](https://github.com/sinclairzx81/typebox) schemas hand-written [TypeBox](https://github.com/sinclairzx81/typebox) schemas
under `src/schemas/` used for runtime validation in `continuum-backend`'s under `src/schemas/` used for runtime validation in `continuum-backend`'s
ElysiaJS routes. ElysiaJS routes.
- `packages/rust-types` a Rust crate (`continuum-rust-types`) that compiles - `packages/rust-types` - a Rust crate (`continuum-rust-types`) that compiles
the same `.proto` files with `prost-build` (via `build.rs`), producing the same `.proto` files with `prost-build` (via `build.rs`), producing
`serde`-derived structs for `continuum-proxy` and `continuum-ai-worker`. `serde`-derived structs for `continuum-proxy` and `continuum-ai-worker`.
+5 -5
View File
@@ -8,18 +8,18 @@ pub use continuum::v1::{
MaterialProfile, PrintJob, PrintJobStatus, PrintParameters, Template, MaterialProfile, PrintJob, PrintJobStatus, PrintParameters, Template,
}; };
// Bambu's raw MQTT command/report structs are NOT modeled here they're // Bambu's raw MQTT command/report structs are NOT modeled here - they're
// plain hand-written Rust + serde in continuum-proxy's // plain hand-written Rust + serde in continuum-proxy's
// src/printer/bambu_commands/, not proto. That data is JSON-over-MQTT // src/printer/bambu_commands/, not proto. That data is JSON-over-MQTT
// (not binary protobuf), and only continuum-proxy ever needs to parse it // (not binary protobuf), and only continuum-proxy ever needs to parse it
// none of protobuf's actual value (cross-language codegen, binary wire // - none of protobuf's actual value (cross-language codegen, binary wire
// efficiency) applies, and forcing it through prost-build's codegen model // efficiency) applies, and forcing it through prost-build's codegen model
// anyway produced real, avoidable friction (see this crate's git history // anyway produced real, avoidable friction (see this crate's git history
// for the specifics: a field/variant attribute-matching collision on // for the specifics: a field/variant attribute-matching collision on
// `oneof`, needing package-scoped `type_attribute` calls, explicit // `oneof`, needing package-scoped `type_attribute` calls, explicit
// `field_attribute(..., "#[serde(default)]")` for fields that aren't // `field_attribute(..., "#[serde(default)]")` for fields that aren't
// always present every one of these disappears with a hand-written // always present - every one of these disappears with a hand-written
// struct, where `Option<T>` and `#[serde(flatten)]` just work with zero // struct, where `Option<T>` and `#[serde(flatten)]` just work with zero
// configuration). Proto stays for continuum.v1 above, which unlike // configuration). Proto stays for continuum.v1 above, which - unlike
// this is a schema we designed ourselves and that both TS and Rust // this - is a schema we designed ourselves and that both TS and Rust
// genuinely need. // genuinely need.
+24 -21
View File
@@ -1,7 +1,7 @@
# bambulab/ JSON Schemas # bambulab/ JSON Schemas
Documentation/validation schemas for Bambu's raw MQTT wire format, mirroring Documentation/validation schemas for Bambu's raw MQTT wire format, mirroring
continuum-proxy's `src/printer/bambu_commands/` not used for codegen (the continuum-proxy's `src/printer/bambu_commands/` - not used for codegen (the
Rust structs there are hand-written; see that module's doc comment for why), Rust structs there are hand-written; see that module's doc comment for why),
but genuinely useful on their own: language-agnostic documentation of the but genuinely useful on their own: language-agnostic documentation of the
wire format, and usable to validate a captured MQTT payload without writing wire format, and usable to validate a captured MQTT payload without writing
@@ -11,11 +11,11 @@ any Rust to do it.
``` ```
bambulab/ bambulab/
envelope.schema.json the base sequence_id + command, shared by envelope.schema.json the base - sequence_id + command, shared by
every command in every generation, so it lives every command in every generation, so it lives
here unversioned, not duplicated under v1/v2 here unversioned, not duplicated under v1/v2
v1/ v1/
request.schema.json BambuRequest dispatcher one key per category request.schema.json BambuRequest dispatcher - one key per category
("info", "pushing", ...), each a oneOf (a ("info", "pushing", ...), each a oneOf (a
category can have more than one request shape) category can have more than one request shape)
report.schema.json BambuReport dispatcher, same idea report.schema.json BambuReport dispatcher, same idea
@@ -27,15 +27,18 @@ bambulab/
report/ report/
info/ info/
get_version.schema.json get_version.schema.json
module_info.schema.json _module_info.schema.json
print/ print/
print.schema.json the ongoing print-state push print.schema.json the ongoing print-state push
ams.schema.json _ams.schema.json
ams_unit.schema.json _ams_unit.schema.json
ams_tray.schema.json _ams_tray.schema.json
xcam.schema.json _vt_tray.schema.json shared base for AmsTray + the virtual/
external spool slot, via allOf + $ref
_upgrade_state.schema.json
_xcam.schema.json
v2/ add the same split once V2's wire format is v2/ add the same split once V2's wire format is
known to differ from V1's removed for now known to differ from V1's - removed for now
rather than leave broken copy-pasted stubs rather than leave broken copy-pasted stubs
``` ```
@@ -43,9 +46,9 @@ bambulab/
whatever a `pushall` request triggers is `report/print/`, not whatever a `pushall` request triggers is `report/print/`, not
`report/pushing/`. Sending `pushall` (which *does* go to the `pushing` key `report/pushing/`. Sending `pushall` (which *does* go to the `pushing` key
on the request side) makes the printer start/refresh an ongoing state-push on the request side) makes the printer start/refresh an ongoing state-push
stream, and that stream arrives under the `print` key a different root stream, and that stream arrives under the `print` key - a different root
key from the request that triggered it. A category folder here means key from the request that triggered it. A category folder here means
"what root key does this arrive under", not "what request caused it" the "what root key does this arrive under", not "what request caused it" - the
first version of this schema got that wrong (see git history) before a first version of this schema got that wrong (see git history) before a
closer read of the real capture caught it. closer read of the real capture caught it.
@@ -65,35 +68,35 @@ Every command/response schema *extends* `envelope.schema.json` with
This is genuinely closer to real inheritance than anything else in this This is genuinely closer to real inheritance than anything else in this
project's schema stack (proto, Rust): the instance must satisfy the base project's schema stack (proto, Rust): the instance must satisfy the base
schema *and* the extension schema simultaneously, and verified with schema *and* the extension schema simultaneously, and - verified with
negative test cases, not just asserted `envelope.schema.json`'s negative test cases, not just asserted - `envelope.schema.json`'s
`required: ["sequence_id", "command"]` is actually enforced on every `required: ["sequence_id", "command"]` is actually enforced on every
schema that extends it, not just copy-pasted as documentation. schema that extends it, not just copy-pasted as documentation.
`v1/report/print/ams_tray.schema.json` is the other JSON-Schema-specific `v1/report/print/_ams_tray.schema.json` is the other JSON-Schema-specific
tool worth knowing: `oneOf`, for "this is exactly one of several tool worth knowing: `oneOf`, for "this is exactly one of several
genuinely different shapes" (an AMS tray slot is either empty just genuinely different shapes" (an AMS tray slot is either empty - just
`id` or loaded the full field set never something in between). `id` - or loaded - the full field set - never something in between).
`oneOf` requires exactly one branch to match; watch out for a base-style `oneOf` requires exactly one branch to match; watch out for a base-style
branch (like `EmptyTray`) accidentally also matching a more specific branch (like `EmptyTray`) accidentally also matching a more specific
branch's instance if the specific branch doesn't require enough fields branch's instance if the specific branch doesn't require enough fields -
verified and fixed once already here, see that file's description. verified and fixed once already here, see that file's description.
**One gotcha if you add a new base-style schema**: don't set **One gotcha if you add a new base-style schema**: don't set
`"additionalProperties": false` on something meant to be `allOf`-extended. `"additionalProperties": false` on something meant to be `allOf`-extended.
`allOf` validates every sub-schema against the *whole* instance `allOf` validates every sub-schema against the *whole* instance
independently it doesn't merge object schemas so a closed base schema independently - it doesn't merge object schemas - so a closed base schema
would reject every field the extending schema adds. Leave would reject every field the extending schema adds. Leave
`additionalProperties` unset (defaults to allowed) on anything used as a `additionalProperties` unset (defaults to allowed) on anything used as a
base; enforce closedness only on the top-level dispatcher schemas base; enforce closedness only on the top-level dispatcher schemas
(`v1/request.schema.json`/`v1/report.schema.json` do this correctly (`v1/request.schema.json`/`v1/report.schema.json` do this correctly -
check their `additionalProperties: false`). check their `additionalProperties: false`).
## `$id` convention ## `$id` convention
Every schema's `$id` is its real Gitea raw-file URL: Every schema's `$id` is its real Gitea raw-file URL:
`https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/...` `https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/...`
a genuinely dereferenceable URI (verified: `raw/branch/main/<path>` is - a genuinely dereferenceable URI (verified: `raw/branch/main/<path>` is
the correct Gitea pattern, not `raw/<path>` or `raw/<branch>/<path>`), the correct Gitea pattern, not `raw/<path>` or `raw/<branch>/<path>`),
rather than a made-up placeholder domain. `$ref`s between files stay rather than a made-up placeholder domain. `$ref`s between files stay
relative paths; `$id` is what a validator uses as the base URI to resolve relative paths; `$id` is what a validator uses as the base URI to resolve
@@ -103,7 +106,7 @@ standalone by anything that wants to dereference it directly.
## Validating something ## Validating something
`$ref` resolution here relies on each schema's `$id` as the base URI for `$ref` resolution here relies on each schema's `$id` as the base URI for
its own relative refs (standard JSON Schema behavior) register schemas its own relative refs (standard JSON Schema behavior) - register schemas
by `$id`, not by filename, or you'll hit collisions (`get_version.schema.json` by `$id`, not by filename, or you'll hit collisions (`get_version.schema.json`
exists under both `request/info/` and `report/info/`): exists under both `request/info/` and `report/info/`):
+1 -1
View File
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/envelope.schema.json", "$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/envelope.schema.json",
"title": "CommandEnvelope", "title": "CommandEnvelope",
"description": "Fields every Bambu MQTT command/response shares, across both protocol generations unversioned, at the bambulab/ root, not duplicated under v1/ or v2/. This is the 'base class' other schemas extend it via allOf + $ref. JSON Schema doesn't have inheritance either, strictly speaking (no 'extends' keyword) allOf is composition: it says the instance must satisfy THIS schema AND whatever else is listed alongside it. It's the closest thing to real inheritance ergonomics of anything used across this project's schema stack (proto, Rust), because $ref + allOf lets you name and reuse a shape without re-declaring its fields, which proto/Rust composition can't quite do (there you still write `common: PrinterReportCommon` by hand on every struct).", "description": "Fields every Bambu MQTT command/response shares, across both protocol generations - unversioned, at the bambulab/ root, not duplicated under v1/ or v2/. This is the 'base class' - other schemas extend it via allOf + $ref. JSON Schema doesn't have inheritance either, strictly speaking (no 'extends' keyword) - allOf is composition: it says the instance must satisfy THIS schema AND whatever else is listed alongside it. It's the closest thing to real inheritance ergonomics of anything used across this project's schema stack (proto, Rust), because $ref + allOf lets you name and reuse a shape without re-declaring its fields, which proto/Rust composition can't quite do (there you still write `common: PrinterReportCommon` by hand on every struct).",
"type": "object", "type": "object",
"properties": { "properties": {
"sequence_id": { "type": "string" }, "sequence_id": { "type": "string" },
+1 -1
View File
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report.schema.json", "$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report.schema.json",
"title": "BambuReport", "title": "BambuReport",
"description": "Matches continuum-proxy's src/printer/bambu_commands::BambuReport. Note the category here is \"print\", not \"pushing\" sending a pushall request (which does go to \"pushing\", see request.schema.json) makes the printer start/refresh the ongoing state-push stream, which itself arrives under \"print\". They're different root keys because a report category means 'what key does this arrive under', not 'what request caused it'. Each category's value is a oneOf for the same reason as request.schema.json: room for more than one shape per category without a rewrite later.", "description": "Matches continuum-proxy's src/printer/bambu_commands::BambuReport. Note the category here is \"print\", not \"pushing\" - sending a pushall request (which does go to \"pushing\", see request.schema.json) makes the printer start/refresh the ongoing state-push stream, which itself arrives under \"print\". They're different root keys because a report category means 'what key does this arrive under', not 'what request caused it'. Each category's value is a oneOf for the same reason as request.schema.json: room for more than one shape per category without a rewrite later.",
"type": "object", "type": "object",
"minProperties": 1, "minProperties": 1,
"maxProperties": 1, "maxProperties": 1,
@@ -0,0 +1,26 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/info/_module_info.schema.json",
"title": "ModuleInfo",
"type": "object",
"properties": {
"name": { "type": "string" },
"sw_ver": { "type": "string" },
"hw_ver": { "type": "string" },
"loader_ver": { "type": "string" },
"product_name": { "type": "string" },
"sn": { "type": "string" },
"visible": { "type": "boolean" },
"flag": { "type": "integer" }
},
"required": [
"name",
"sw_ver",
"hw_ver",
"loader_ver",
"sn",
"product_name",
"visible",
"flag"
]
}
@@ -12,7 +12,7 @@
"reason": { "type": "string" }, "reason": { "type": "string" },
"module": { "module": {
"type": "array", "type": "array",
"items": { "$ref": "module_info.schema.json" } "items": { "$ref": "_module_info.schema.json" }
} }
}, },
"required": ["module"] "required": ["module"]
@@ -1,13 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/info/module_info.schema.json",
"title": "ModuleInfo",
"type": "object",
"properties": {
"hw_ver": { "type": "string" },
"name": { "type": "string" },
"sn": { "type": "string" },
"sw_ver": { "type": "string" }
},
"required": ["hw_ver", "name", "sn", "sw_ver"]
}
@@ -0,0 +1,25 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/_ams.schema.json",
"title": "AmsState",
"description": "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.",
"type": "object",
"properties": {
"ams": {
"type": "array",
"items": { "$ref": "_ams_unit.schema.json" }
},
"ams_exists_bits": { "type": "string" },
"tray_exist_bits": { "type": "string" },
"tray_is_bbl_bits": { "type": "string" },
"tray_tar": { "type": "string" },
"tray_now": { "type": "string" },
"tray_pre": { "type": "string" },
"tray_read_done_bits": { "type": "string" },
"tray_reading_bits": { "type": "string" },
"version": { "type": "integer" },
"insert_flag": { "type": "boolean" },
"power_on_flag": { "type": "boolean" }
},
"required": ["ams"]
}
@@ -0,0 +1,37 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/_ams_tray.schema.json",
"title": "AmsTray",
"description": "A tray slot is either empty (just `id`) or loaded (the full field set) - two genuinely different shapes for the same slot, not one shape with optional fields. oneOf says the instance must match EXACTLY one of these. Note LoadedTray requires every field it lists, not just `id` - with only `id` required, a bare {\"id\":\"0\"} would validate against BOTH branches at once (it trivially satisfies Loaded's single requirement too) and oneOf would fail, since oneOf demands exactly one match. Verified this the hard way - see git history. The Rust equivalent is an untagged enum with #[serde(deny_unknown_fields)] on the Empty variant, for the same reason in reverse: without it, a loaded tray's extra fields wouldn't be rejected by Empty, and untagged enums try variants in order - see bambu_commands/print.rs. `drying_time` and `drying_temp` fields are only available for AMS 2 and AMS HT - AMS 1 doesn't have the drying option.",
"oneOf": [
{
"title": "EmptyTray",
"type": "object",
"properties": {
"id": { "type": "string" }
},
"required": ["id"],
"additionalProperties": false
},
{
"allOf": [
{ "$ref": "./_vt_tray.schema.json" },
{
"title": "LoadedTray",
"type": "object",
"properties": {
"state": { "type": "integer" },
"total_len": { "type": "number" },
"ctype": { "type": "integer" },
"cols": { "type": "array", "items": { "type": "string" } },
"drying_time": { "type": "string" },
"drying_temp": { "type": "string" }
},
"required": [
"state", "total_len", "ctype", "cols"
]
}
]
}
]
}
@@ -1,17 +1,23 @@
{ {
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/ams_unit.schema.json", "$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/_ams_unit.schema.json",
"title": "AmsUnit", "title": "AmsUnit",
"description": "One physical AMS unit (Bambu's numbering starts at 0 via `id`).", "description": "One physical AMS unit (Bambu's numbering starts at 0 via `id`).",
"type": "object", "type": "object",
"properties": { "properties": {
"humidity": { "type": "string" },
"id": { "type": "string" },
"temp": { "type": "string" },
"tray": { "tray": {
"type": "array", "type": "array",
"items": { "$ref": "ams_tray.schema.json" } "items": { "$ref": "_ams_tray.schema.json" }
} },
"chip_id": { "type": "string" },
"ams_id": { "type": "string" },
"check": { "type": "integer" },
"id": { "type": "string" },
"humidity": { "type": "string" },
"humidity_raw": { "type": "string" },
"temp": { "type": "string" },
"dry_time": { "type": "integer" },
"info": { "type": "string" }
}, },
"required": ["humidity", "id", "temp", "tray"] "required": ["humidity", "id", "temp", "tray"]
} }
@@ -0,0 +1,21 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/_upgrade_state.schema.json",
"title": "UpgradeState",
"type": "object",
"properties": {
"sequence": { "type": "string" },
"progress": { "type": "string" },
"status": { "type": "string", "enum": ["IDLE"]},
"consistency_request": { "type": "boolean" },
"dis_state": { "type": "integer" },
"err_code": { "type": "integer" },
"force_upgrade": { "type": "boolean" },
"message": { "type": "string" },
"module": { "type": "string" },
"new_version_state": { "type": "integer" },
"cur_state_code": { "type": "integer" },
"idx2": { "type": "integer" },
"new_ver_list": { "type": "array", "items": { "type": "string" } }
}
}
@@ -0,0 +1,36 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/_vt_tray.schema.json",
"title": "VtTray",
"description": "This schema is used as Virtual Tray (external spool) or as a base for AmsTray. When empty, all values are zeroed and `tray_color` field is set to \"FFFFFF00\".",
"type": "object",
"properties": {
"id": { "type": "string" },
"tag_uid": { "type": "string" },
"tray_id_name": { "type": "string" },
"tray_info_idx": { "type": "string" },
"tray_type": { "type": "string" },
"tray_sub_brands": { "type": "string" },
"tray_color": { "type": "string" },
"tray_weight": { "type": "string" },
"tray_diameter": { "type": "string" },
"tray_temp": { "type": "string" },
"tray_time": { "type": "string" },
"bed_temp_type": { "type": "string" },
"bed_temp": { "type": "string" },
"nozzle_temp_min": { "type": "string" },
"nozzle_temp_max": { "type": "string" },
"xcam_info": { "type": "string" },
"tray_uuid": { "type": "string" },
"remain": { "type": "integer", "minimum": 0 },
"k": { "type": "number" },
"n": { "type": "number" },
"cali_idx": { "type": "number" }
},
"required": [
"id", "remain", "bed_temp", "bed_temp_type",
"nozzle_temp_max", "nozzle_temp_min", "tag_uid", "tray_color",
"tray_diameter", "tray_id_name", "tray_info_idx", "tray_sub_brands",
"tray_type", "tray_uuid", "tray_weight", "xcam_info", "k", "n"
]
}
@@ -1,6 +1,6 @@
{ {
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/xcam.schema.json", "$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/_xcam.schema.json",
"title": "XcamSettings", "title": "XcamSettings",
"description": "Camera-based AI print monitoring settings (spaghetti detection, first-layer inspection, etc.).", "description": "Camera-based AI print monitoring settings (spaghetti detection, first-layer inspection, etc.).",
"type": "object", "type": "object",
@@ -1,14 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/ams.schema.json",
"title": "AmsState",
"description": "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.",
"type": "object",
"properties": {
"ams": {
"type": "array",
"items": { "$ref": "ams_unit.schema.json" }
}
},
"required": ["ams"]
}
@@ -1,48 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/ams_tray.schema.json",
"title": "AmsTray",
"description": "A tray slot is either empty (just `id`) or loaded (the full field set) — two genuinely different shapes for the same slot, not one shape with optional fields. oneOf says the instance must match EXACTLY one of these. Note LoadedTray requires every field it lists, not just `id` — with only `id` required, a bare {\"id\":\"0\"} would validate against BOTH branches at once (it trivially satisfies Loaded's single requirement too) and oneOf would fail, since oneOf demands exactly one match. Verified this the hard way — see git history. The Rust equivalent is an untagged enum with #[serde(deny_unknown_fields)] on the Empty variant, for the same reason in reverse: without it, a loaded tray's extra fields wouldn't be rejected by Empty, and untagged enums try variants in order — see bambu_commands/print.rs.",
"oneOf": [
{
"title": "EmptyTray",
"type": "object",
"properties": {
"id": { "type": "string" }
},
"required": ["id"],
"additionalProperties": false
},
{
"title": "LoadedTray",
"type": "object",
"properties": {
"id": { "type": "string" },
"bed_temp": { "type": "string" },
"bed_temp_type": { "type": "string" },
"cols": { "type": "array", "items": { "type": "string" } },
"drying_temp": { "type": "string" },
"drying_time": { "type": "string" },
"nozzle_temp_max": { "type": "string" },
"nozzle_temp_min": { "type": "string" },
"remain": { "type": "integer" },
"tag_uid": { "type": "string" },
"tray_color": { "type": "string" },
"tray_diameter": { "type": "string" },
"tray_id_name": { "type": "string" },
"tray_info_idx": { "type": "string" },
"tray_sub_brands": { "type": "string" },
"tray_type": { "type": "string" },
"tray_uuid": { "type": "string" },
"tray_weight": { "type": "string" },
"xcam_info": { "type": "string" }
},
"required": [
"id", "bed_temp", "bed_temp_type", "cols", "drying_temp", "drying_time",
"nozzle_temp_max", "nozzle_temp_min", "remain", "tag_uid", "tray_color",
"tray_diameter", "tray_id_name", "tray_info_idx", "tray_sub_brands",
"tray_type", "tray_uuid", "tray_weight", "xcam_info"
]
}
]
}
@@ -2,16 +2,22 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/print.schema.json", "$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/report/print/print.schema.json",
"title": "PrintReport", "title": "PrintReport",
"description": "The ongoing print-state push (root key \"print\") NOT a direct reply to the pushall request (that goes to \"pushing\", see request/pushing/pushall.schema.json). Sending pushall makes the printer start/refresh this stream; it isn't itself request/response, which is also why this is its own category folder rather than sitting under pushing/ a category here is 'what root key does this arrive under', not 'what triggered it'. Doesn't extend envelope.schema.json: the example seen so far doesn't show sequence_id/command on this one, and it may genuinely not carry them (an async push, not a direct reply) — revisit if a real capture proves otherwise. The real payload has many more fields than shown here (this example was truncated) — add them under `properties` the same way you'd add them to bambu_commands/print.rs.", "description": "The ongoing print-state push (root key \"print\") - NOT a direct reply to the pushall request (that goes to \"pushing\", see request/pushing/pushall.schema.json). Sending pushall makes the printer start/refresh this stream; it isn't itself request/response, which is also why this is its own category folder rather than sitting under pushing/ - a category here is 'what root key does this arrive under', not 'what triggered it'.",
"type": "object", "allOf": [
"properties": { { "$ref": "../../../envelope.schema.json" },
"ams": { "$ref": "ams.schema.json" }, {
"ams_exist_bits": { "type": "string" }, "type": "object",
"insert_flag": { "type": "boolean" }, "properties": {
"power_on_flag": { "type": "boolean" }, "ams": { "$ref": "_ams.schema.json" },
"tray_exist_bits": { "type": "string" }, "ams_exist_bits": { "type": "string" },
"tray_is_bbl_bits": { "type": "string" }, "insert_flag": { "type": "boolean" },
"xcam": { "$ref": "xcam.schema.json" }, "power_on_flag": { "type": "boolean" },
"xcam_status": { "type": "string" } "tray_exist_bits": { "type": "string" },
} "tray_is_bbl_bits": { "type": "string" },
"upgrade_state": { "$ref": "_upgrade_state.schema.json" },
"xcam": { "$ref": "_xcam.schema.json" },
"xcam_status": { "type": "string" }
}
}
]
} }
+1 -1
View File
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/request.schema.json", "$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/bambulab/v1/request.schema.json",
"title": "BambuRequest", "title": "BambuRequest",
"description": "Matches continuum-proxy's src/printer/bambu_commands::BambuRequest one JSON key naming the category ('info', 'pushing', ...). Each category's value is a oneOf, not a single $ref: a category can have more than one possible request shape (e.g. 'info' might grow a second command besides get_version) oneOf leaves room for that from the start instead of needing a rewrite the day it happens.", "description": "Matches continuum-proxy's src/printer/bambu_commands::BambuRequest - one JSON key naming the category ('info', 'pushing', ...). Each category's value is a oneOf, not a single $ref: a category can have more than one possible request shape (e.g. 'info' might grow a second command besides get_version) - oneOf leaves room for that from the start instead of needing a rewrite the day it happens.",
"type": "object", "type": "object",
"minProperties": 1, "minProperties": 1,
"maxProperties": 1, "maxProperties": 1,
@@ -8,7 +8,7 @@
"type": "object", "type": "object",
"properties": { "properties": {
"command": { "const": "pushall" }, "command": { "const": "pushall" },
"version": { "type": "integer" }, "version": { "type": "integer", "minimum": 1, "maximum": 1 },
"push_target": { "type": "integer" } "push_target": { "type": "integer" }
}, },
"required": ["version", "push_target"] "required": ["version", "push_target"]