Continuum is intended to be sold, so every dependency has to permit distribution in closed-source commercial software. This crate carried `license = "UNLICENSED"`, which is not valid SPDX and made `cargo deny` fail outright; `LicenseRef-Proprietary` with `publish = false` is what marks it first-party instead. The note in deny.toml is the part that earns its keep: `src/go2rtc.rs` spawns go2rtc from PATH and expects the operator to have installed it, so we currently distribute nothing. go2rtc shells out to ffmpeg, and ffmpeg is LGPL-2.1+ only when built without `--enable-gpl` - most prebuilt binaries are GPL builds because they bundle x264. If we ever ship either binary, those build flags become our problem. Policy and full audit: continuum-common's docs/LICENSES.md.
continuum-proxy
Edge gateway daemon for the Continuum print farm platform. Runs on a Linux
SBC on-site, talks to printers over the LAN, and keeps a connection to the
cloud control plane (continuum-backend).
What's real right now
- Bambu MQTT - a real client for both protocol generations (MQTT
v3.1.1+BambuMQTT v1 on older firmware, MQTT v5+BambuMQTT v2 on current
firmware), auto-detected per printer on connect (a firmware update can
move the same physical printer between them, so this isn't something
config can hard-code once and forget - see
printer/bambu.rs'sBambuProtocolPreference::Auto). Request/reply correlation viasequence_id, an in-memoryprint.push_statuscache that merges v1's partial updates and replaces on v2's full ones, and TLS trust that auto-pins a printer's certificate via trust-on-first-connect the first time the bundled CA doesn't verify (printer/bambu.rs'sensure_trusted) - seeprinter/bambu_mqtt.rs's doc comment for the full protocol write-up. - Marlin/RepRap serial - a real held-open serial connection that paces
gcode lines by Marlin's own "ok" acknowledgment (
printer/marlin_serial.rs). - Wire shapes from schemas, not hand duplication - Bambu's raw MQTT
JSON is built straight from
continuum-schemas' JSON Schema files viacontinuum-schema-instance, instead of a second hand-written copy of every request shape drifting out of sync with the schema. - Cloud uplink - a WebSocket client to
continuum-backendthat connects, sends a heartbeat on a timer, and reconnects on drop (src/uplink/). - go2rtc watchdog - restarts the camera-restreaming subprocess if it
dies (
src/go2rtc.rs).
What's still a stub
PrusaLink (REST) and Klipper/Moonraker (WebSocket) - printer/prusa.rs
and printer/klipper.rs just println! what they'd send. Also not built
yet: dispatching a cloud-issued command to a connected printer (the uplink
and the printer fleet run side by side in main.rs, but nothing routes
between them yet), local buffering for telemetry across connectivity gaps,
LAN printer discovery (SSDP/mDNS), and the mechanical plate-changer
interface.
Getting started
cp .env.example .env
cargo run # the daemon: connects every configured printer, then runs the cloud uplink + go2rtc watchdog
cp printers.example.toml printers.toml # fill in your real printers (gitignored)
cargo run --example auto_connect_bambu # checks/auto-pins each Bambu printer's certificate, no MQTT needed
cargo run --example test_bambu_certs # narrower: just the raw TLS handshake, no auto-pinning
cargo run --example printer_polymorphism # standalone trait+enum demo, fake data, no network/env needed
cargo run --example bambu_commands_demo # round-trips hand-written structs against real captured Bambu JSON
Structure
src/
main.rs Loads+connects the printer fleet, then runs the uplink and go2rtc watchdog side by side
config.rs Loads settings from environment variables
fleet.rs Loads printers.toml into ready-to-use PrinterHandles
uplink/ WebSocket client to continuum-backend: connect, heartbeat, reconnect on drop
go2rtc.rs Restarts the go2rtc camera-restreaming process if it dies
printer/
mod.rs GenericPrinter trait + PrinterBase + PrinterHandle enum - the trait+enum
"inheritance" pattern this project uses instead of class inheritance
bambu.rs The real Bambu printer type: cert trust, protocol version auto-detect, commands
bambu_mqtt.rs The real MQTT wiring underneath bambu.rs - see its doc comment for the protocol details
bambu_commands/ Hand-written serde structs mirroring continuum-schemas' bambulab/ shapes
marlin_serial.rs A real held-open Marlin/RepRap serial connection
prusa.rs, klipper.rs Still stubs - see "What's still a stub" above
examples/
auto_connect_bambu.rs Checks/auto-pins every Bambu printer's certificate (no MQTT)
test_bambu_certs.rs Narrower: just a raw TLS handshake per Bambu printer
printer_polymorphism.rs Standalone trait+enum demo, five fake printers, no network needed
bambu_commands_demo.rs Round-trips bambu_commands' structs against real captured Bambu JSON
printers.toml (gitignored - copy from printers.example.toml) holds real
per-printer connection details: host, access code/API key/serial port
depending on vendor, and - for Bambu - an optional per-printer CA
certificate override (see certs/README.md; most printers don't need one,
since connect() auto-pins automatically).
Learning Rust through this repo
src/printer/mod.rs's doc comment is where the "how do I do inheritance
without classes" question lives - trait (shared behavior) + struct
(shared fields) + enum (the closed set of concrete types), instead of
GenericPrinter -> BambuPrinter/PrusaLinkPrinter/... class inheritance.
Run printer_polymorphism to see it work end to end without needing any
real printer on the network.