Files
continuum-proxy/Cargo.toml
T
octoturgeandClaude Opus 5 704b65ac26 Add real FTPS upload to Bambu printers
`upload_project_file` was a `println!`. MQTT can start a print but can
only name a file the printer already has, so moving the bytes there is a
separate protocol: implicit FTPS on port 990, user `bblp`, password the
same access code MQTT uses, into the printer's own `cache/` directory.

Confirmed live against a P1P: 102 bytes uploaded, byte count matched
exactly, first attempt.

Deliberately suppaftp's *blocking* client on `tokio::task::spawn_blocking`
rather than its async one. The blocking client takes a plain
`native_tls::TlsConnector`, so this reuses `BambuTls::build_connector()`
unchanged and every TLS trust decision for a printer stays in that one
method; the async client needs a second TLS stack (`async-native-tls`)
whose futures-vs-tokio `AsyncRead` mismatch has already cost this project
a debugging session. `connect()`'s doc comment already pointed at
`spawn_blocking` as the eventual answer for blocking work, and a
multi-megabyte upload earns it more obviously than a handshake does.

`connect_secure_implicit` sits behind suppaftp's `deprecated` feature
because implicit FTPS is what the RFCs deprecated in favour of explicit
AUTH TLS. The printers only speak implicit, so the feature is on.

Split into `upload_file` (FTPS only) and `start_uploaded_file` (the MQTT
command that begins printing), because the two halves have very different
consequences: moving a file onto a printer is inert and reversible, while
starting a print commits the machine to hours of physical work. That split
is what made the transfer testable against real hardware at all.

`start_uploaded_file` dispatches on file type - a `.3mf` is a container so
`print.project_file` needs both a `url` and a `param` naming the gcode
inside it, while a bare `.gcode` has nothing to select and
`print.gcode_file` takes just a path. It has deliberately never been
fired; its doc comment lists the three guesses to confirm first.

suppaftp is MIT OR Apache-2.0, checked against docs/LICENSES.md before
being added, along with all 22 crates it pulled in.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-03 10:11:36 +00:00

78 lines
2.6 KiB
TOML

[package]
name = "continuum-proxy"
version = "0.1.0"
edition = "2024"
description = "Continuum edge gateway daemon - runs on-site, bridges printers to the cloud control plane"
# Proprietary: deliberately not an SPDX id, so cargo-deny treats it as
# first-party. See docs/LICENSES.md in continuum-common.
license = "LicenseRef-Proprietary"
publish = false
[lib]
name = "continuum_proxy"
path = "src/lib.rs"
[[bin]]
name = "continuum-proxy"
path = "src/main.rs"
[[example]]
name = "printer_polymorphism"
path = "examples/printer_polymorphism.rs"
[[example]]
name = "test_bambu_certs"
path = "examples/test_bambu_certs.rs"
[[example]]
name = "auto_connect_bambu"
path = "examples/auto_connect_bambu.rs"
[[example]]
name = "bambu_commands_demo"
path = "examples/bambu_commands_demo.rs"
[[example]]
name = "live_reports"
path = "examples/live_reports.rs"
[[example]]
name = "bambu_idle_checks"
path = "examples/bambu_idle_checks.rs"
[dependencies]
# 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" }
# Builds a JSON instance straight from the schema files in
# continuum-schemas/schemas/ - used for Bambu's raw MQTT JSON messages
# instead of hand-written serde structs (see bambu.rs).
continuum-schema-instance = { path = "../continuum-common/packages/rust-schema-instance" }
tokio = { version = "1.40", features = ["full"] }
tokio-tungstenite = { version = "0.24", features = ["native-tls"] }
futures-util = "0.3"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
toml = "0.8"
native-tls = "0.2"
base64 = "0.22"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
anyhow = "1"
thiserror = "1"
dotenvy = "0.15"
tokio-serial = { version = "5.5.0", default-features = false }
rumqttc = { version = "0.25.1", default-features = false, features = ["use-native-tls"] }
# Blocking FTPS client for pushing project files to a printer's own
# storage (see src/printer/bambu_ftps.rs for why the blocking one, not
# the async one). `deprecated` is what gates `connect_secure_implicit`:
# Bambu speaks implicit FTPS on 990, which the RFCs deprecated in favour
# of explicit AUTH TLS. The printers do not care.
# MIT OR Apache-2.0 - checked against docs/LICENSES.md before adding.
suppaftp = { version = "12.1.1", features = ["native-tls", "deprecated"] }