Print like a chef. Monitor your spaghetti.
SpaghettiChef is a Java-based local runtime for monitoring and controlling 3D printers through an embedded dashboard, REST API, persistent runtime state, controlled printer workflows, and camera-based visual analysis.
SpaghettiChef is local-first. One runtime supervises one local printer farm through USB-connected or simulated printers. The current hardware reference is a Marlin-compatible Creality Ender-series printer, while simulation support keeps the runtime testable without physical hardware.
The project currently combines:
- local multi-printer runtime management
- embedded browser dashboard
- REST API
- SQLite-backed runtime state
- background printer monitoring
- controlled print-job and printer-action workflows
- host-to-printer SD-card upload diagnostics
- local role/security and operator audit records
- camera capture and persisted image analysis
- camera storage reconciliation for imported/archive datasets
- configurable Java and external CLI calculation engines
- experimental Rust-based image analysis tooling
For the detailed version plan, see docs/roadmap.md.
SpaghettiChef provides a structured local control layer around 3D printers.
At the current stage, it can:
- register and monitor multiple printers
- work with simulated and USB-connected printers
- expose printer state through a REST API
- serve an embedded dashboard from the same runtime
- create and start controlled print jobs
- upload
.gcodefiles to printer-side SD storage - track upload progress and recovery behavior
- persist printer events, job events, camera events, and audit history
- configure camera capture per printer
- capture live snapshots
- retain source snapshots under camera jobs
- generate persisted delta frames
- run persisted calculation workflows
- review camera analysis sessions
- replay and inspect persisted camera data
- import camera archive datasets for repeatable engine tests
- configure calculation engines from the dashboard
- run Java or external CLI image analyzers over the same delta data
SpaghettiChef does not currently try to replace a slicer or a full production MES. It focuses on the local runtime layer: printer communication, control, observation, persistence, and operator-facing diagnostics.
The current technical focus is the camera and visual-analysis subsystem: turning captured or imported image history into repeatable calculation runs that can be compared across engines.
The 0.4.x work established a persisted camera model:
Camera Job
↓
Source Snapshots
↓
Delta Sets
↓
Calculation Runs
↓
Analysis Session Review
The 0.5.x work introduced an independent Rust image-analysis track. The Rust tool started as a standalone CLI analyzer, then became callable from the Java runtime as an optional calculation engine.
The 0.6.x work made persisted camera data easier to inspect, replay, delete, and keep aligned with the filesystem.
The 0.7.x work adds the dataset and engine-settings layer:
- runtime-compatible camera archive datasets under
dataset/ - storage/database synchronization for restored or imported camera files
- manually labeled examples for later benchmark reports
- persisted multi-engine settings for Java and external CLI analyzers
- dashboard-based engine selection and per-run parameter overrides
The 1.0.x work opens the first central read-only VPS viewer track. This is a teaser slice, not remote control: local farms stay private, push selected state outbound, and the VPS keeps a separate aggregate database for registration, heartbeat, overview, and a minimal central dashboard.
flowchart TB
dashboard["Embedded dashboard"]
api["Java REST API"]
runtime["SpaghettiChef runtime"]
db["SQLite persistence"]
monitoring["Monitoring scheduler"]
jobs["Job and action services"]
serial["Serial / simulated printer layer"]
camera["Camera capture and analysis"]
engines["Calculation engines<br/>Java / external CLI"]
dataset["Runtime archive dataset"]
printers["3D printers"]
dashboard <--> api
api <--> runtime
runtime <--> db
runtime <--> monitoring
runtime <--> jobs
runtime <--> camera
runtime <--> engines
jobs --> serial
monitoring --> serial
serial --> printers
dataset -. sync .-> camera
camera --> engines
SpaghettiChef keeps the Java runtime as the owner of API, persistence, dashboard, scheduling, printer workflows, and camera-job state. External image analyzers are treated as optional calculation engines, not as replacement backends.
The emerging central VPS viewer is a separate read-only mode. It does not initialize local printer communication, camera capture, printer monitoring, or local jobs.
SpaghettiChef includes an embedded dashboard served by the local runtime.
The dashboard separates global runtime administration from selected-printer operation.
SpaghettiChef
├── Farm Home
├── Printers
├── Jobs
├── Monitoring
├── History
└── Settings
Selected Printer
├── Home
├── Print
├── SD Card
├── Prepare
├── Control
├── Info
├── History
└── Camera / Analysis
The camera and admin views expose persisted camera data:
Admin / Camera Data
├── camera jobs
├── retained source snapshots
├── delta sets
├── calculation runs
├── recalculation workflows
└── engine comparison workflows
The dashboard uses the API layer. It does not talk directly to serial devices or filesystem internals.
The screenshots below provide a visual overview of the current runtime, dashboard, camera analysis, and Rust analyzer work.
Farm Home
|
Selected Printer → Home
|
Selected Printer → Print
|
SD Card Management
|
Camera Analysis
|
Admin Camera Data
|
Analysis Review
|
Rust img-analyzer terminal output
|
SpaghettiChef includes a camera pipeline for per-printer image capture and persisted analysis.
The current camera model distinguishes live preview files from persisted analysis data.
Live preview files
├── latest.jpg
├── previous.jpg
└── delta.jpg
Persisted analysis data
├── camera jobs
├── source snapshots
├── delta sets
├── delta frames
├── calculation runs
└── calculation results
Live files are volatile working files. Persisted review and recalculation use database-owned source snapshots, delta frames, and calculation results.
flowchart TB
manual["Manual capture"]
live["Update live preview files<br/>latest / previous / delta"]
jobcapture["Camera job capture"]
job["Camera job"]
snapshot["Retained source snapshot"]
entry["camera_snapshot_entries"]
deltaset["Delta set"]
deltaframe["Delta frame"]
calculationrun["Calculation run"]
result["Calculation result"]
review["Analysis session review"]
manual --> live
jobcapture --> job
jobcapture --> live
job --> snapshot
snapshot --> entry
entry --> deltaset
deltaset --> deltaframe
deltaframe --> calculationrun
calculationrun --> result
result --> review
A camera job owns retained source snapshots for one camera run.
data/camera/<printerId>/
├── latest.jpg
├── previous.jpg
├── delta.jpg
├── snapshots/
│ └── <cameraJobId>/
│ ├── <snapshotEntryId>_snapshot.jpg
│ └── ...
└── deltas/
└── <cameraJobId>/
└── <deltaSetId>/
├── <from>_<to>_delta.jpg
└── ...
A camera job may be linked to a print job, but it is not a print job. Camera jobs do not execute printer commands, movement, upload, pause, cancel, or print-start actions.
A delta set is generated from the source snapshots of one camera job.
A calculation run is generated from one selected delta set.
This separation allows multiple analysis attempts over the same camera data:
Camera Job 12
├── Delta Set 1
│ ├── Calculation Run 1
│ └── Calculation Run 2
└── Delta Set 2
└── Calculation Run 3
That makes recalculation and future engine comparison possible without overwriting previous analysis results.
SpaghettiChef includes a runtime-compatible dataset folder for repeatable image-analysis work.
The dataset can hold camera files copied from another machine:
dataset/<printerId>/
├── snapshots/<cameraJobId>/
└── deltas/<cameraJobId>/<deltaSetId>/
Dataset metadata and labels live separately under:
dataset/json/<printerId>/
This lets archived camera files keep their original runtime layout while the local test database is recreated from scripts and storage synchronization.
The current sync endpoint reconciles configured camera storage with database rows:
POST /admin/camera/storage/{printerId}/sync
The sync is deliberately a generic camera storage/database reconciliation service. It does not read dataset labels, manifests, or model metadata.
Calculation engines are configured from the dashboard settings. A built-in Java engine and external CLI engines can run against the same delta sets, and recalculation can override experiment parameters for one run without changing persisted defaults.
The Rust track adds an experimental image-analysis component that can be used as an external CLI calculation engine.
The Rust analyzer lives under:
rust/img-analyzer/
It can still be built and run independently from the Java backend:
Example:
cd rust/img-analyzer
cargo run -- \
--from-snapshot ../../camera/p1/previous.jpg \
--to-snapshot ../../camera/p1/latest.jpg \
--method delta-basic \
--threshold 0.20Example output:
{
"engineName": "RUST_CLI_DELTA",
"engineVersion": "0.7.0",
"algorithmVariant": "FRAME_DELTA",
"confidence": 0.0148,
"suspected": false,
"reasonCodes": [],
"message": "No large visual difference detected between snapshots.",
"metrics": {
"changedPixelRatio": 0.00007,
"averagePixelDelta": 0.0148
}
}The Rust tool is not a second REST backend. Java remains the runtime owner, and Rust is configured through the calculation-engine settings as an external analyzer.
flowchart LR
data["Persisted camera data<br/>snapshots / deltas"]
javaEngine["Java calculation engine"]
rustEngine["Rust CLI analyzer<br/>(external engine)"]
result["CameraCalculationResult"]
dashboard["Dashboard review"]
data --> javaEngine
data --> rustEngine
javaEngine --> result
rustEngine --> result
result --> dashboard
SpaghettiChef monitors each configured printer node through the runtime scheduler.
The runtime state model is shared by simulated and USB-connected printers.
flowchart TB
configured["Configured printer"] --> enabled{"Enabled?"}
enabled -- "No" --> disconnected["DISCONNECTED"]
enabled -- "Yes" --> connecting["CONNECTING"]
connecting --> poll{"Poll outcome"}
poll -- "timeout / disconnect / failure" --> error["ERROR"]
poll -- "busy / printing" --> printing["PRINTING"]
poll -- "hotend above threshold" --> heating["HEATING"]
poll -- "ok / T:" --> idle["IDLE"]
poll -- "unclassified response" --> unknown["UNKNOWN"]
error --> connecting
printing --> connecting
heating --> connecting
idle --> connecting
unknown --> connecting
Defined states:
DISCONNECTED
CONNECTING
IDLE
HEATING
PRINTING
ERROR
UNKNOWN
Monitoring data is persisted as runtime state and event history, so the dashboard can show current state and recent operational events.
SpaghettiChef uses backend jobs for controlled runtime operations.
Current job and action capabilities include:
- job creation and listing
- printer assignment
- asynchronous controlled job start
- job cancellation and deletion
- job event visibility
- execution-step diagnostics
- registered printer-side SD targets
- file-backed
PRINT_FILEjobs - guarded printer action workflows
Controlled action scope includes:
READ_TEMPERATURE
READ_POSITION
READ_FIRMWARE_INFO
HOME_AXES
SET_NOZZLE_TEMPERATURE
SET_BED_TEMPERATURE
SET_FAN_SPEED
TURN_FAN_OFF
PRINT_FILE
A PRINT_FILE job references a registered printer-side SD target. SpaghettiChef can register a host-side .gcode file, upload it to printer-side SD storage through a guarded transfer session, and request a firmware-side print start.
SpaghettiChef does not currently slice models, edit G-code, or line-stream a full print from the host as its main workflow.
Host-to-printer SD-card upload is one of the main real-printer verification paths.
SpaghettiChef exposes upload visibility through the API and dashboard.
Upload diagnostics include:
- upload state
- file name
- confirmed lines / total lines
- confirmed bytes / total bytes
- elapsed time
- estimated remaining time
- bytes per second
- lines per second
- rejected/resend count
- transfer quality
- current transfer mode
- configured and active batch sizes
- stability and recovery pressure
- last adaptation reason
This makes long serial transfers observable instead of opaque.
SpaghettiChef includes a local role model for runtime operations.
Roles include:
VIEWER
OPERATOR
ADMIN
Dangerous or state-changing actions can require confirmation, including heating, movement, print start/cancel, SD delete, upload overwrite, and raw command paths.
SpaghettiChef persists operator audit records for accepted and rejected state-changing actions.
SpaghettiChef keeps runtime state in SQLite and filesystem-backed working directories.
Typical local development data includes:
spaghettichef.db
data/
camera/
spaghettichef-print-files/
Development runtime data and generated camera files are ignored by Git.
Build and verify:
mvn clean verifyStart the local runtime with an explicit database file and API port:
mvn \
-Dexec.mainClass="spaghettichef.local.LocalMain" \
-Dspaghettichef.databaseFile="spaghettichef.db" \
-Dspaghettichef.api.port=18080 \
exec:javaOpen the dashboard:
http://localhost:18080/dashboard
The dashboard uses relative API requests, so it follows the port used by the embedded server.
Central read-only viewer teaser:
mvn \
-Dexec.mainClass="spaghettichef.central.CentralMain" \
-Dspaghettichef.api.port=18180 \
-Dspaghettichef.central.databaseFile=spaghettichef-central.db \
exec:javaOpen:
http://localhost:18180/central-dashboard
In this first slice, farm registration and heartbeat can be tested with manual
curl calls. The automatic local-to-central push client is a later 1.0.x step.
The Rust analyzer can be run directly for local experiments, or configured as an external CLI engine from the dashboard settings.
Build and test:
cd rust/img-analyzer
cargo fmt
cargo test
cargo buildRun against two image files:
cargo run -- \
--from-snapshot ../../camera/p1/previous.jpg \
--to-snapshot ../../camera/p1/latest.jpg \
--method delta-basic \
--threshold 0.20For details, see:
Common local endpoints:
GET /health
GET /printers
GET /printers/{id}
GET /printers/{id}/status
POST /printers
PUT /printers/{id}
POST /jobs
POST /jobs/{id}/start
GET /jobs
GET /jobs/{id}/events
GET /settings/monitoring
PUT /settings/monitoring
Camera endpoints include diagnostic live snapshot access and admin camera-data workflows:
POST /printers/{printerId}/camera/snapshot
GET /printers/{printerId}/camera/snapshot
POST /printers/{printerId}/camera/jobs/start
POST /printers/{printerId}/camera/jobs/stop
GET /printers/{printerId}/camera/jobs/active
GET /admin/camera/snapshot/jobs?printerId=<printerId>
GET /admin/camera/snapshot/jobs/{cameraJobId}/timeline?printerId=<printerId>
GET /admin/camera/snapshot/files/{snapshotEntryId}
POST /admin/camera/storage/{printerId}/sync
GET /admin/camera/calculation-engine-settings
PUT /admin/camera/calculation-engine-settings/{engineName}
For the full API surface, see docs/rest-api.md.
spaghetti-chef/
├── README.md
├── Jenkinsfile
├── docs/
│ ├── roadmap.md
│ ├── camera.md
│ ├── dashboard.md
│ ├── quickstart.md
│ ├── install.md
│ ├── developer.md
│ ├── devops.md
│ └── TODOs/
├── src/
│ ├── main/
│ │ ├── java/spaghettichef/
│ │ │ ├── Main.java
│ │ │ ├── local/
│ │ │ │ ├── api/
│ │ │ │ ├── camera/
│ │ │ │ ├── command/
│ │ │ │ ├── config/
│ │ │ │ ├── job/
│ │ │ │ ├── monitoring/
│ │ │ │ ├── persistence/
│ │ │ │ ├── runtime/
│ │ │ │ ├── security/
│ │ │ │ └── serial/
│ │ │ ├── central/
│ │ │ │ ├── api/
│ │ │ │ ├── persistence/
│ │ │ │ └── service/
│ │ │ └── shared/
│ │ └── resources/
│ │ ├── dashboard/
│ │ └── central-dashboard/
│ └── test/
│ └── java/spaghettichef/
├── rust/
│ └── img-analyzer/
├── ops/
├── tools/
├── pom.xml
└── LICENSE
The detailed roadmap is maintained in:
Current direction:
0.4.x Camera jobs, persisted snapshots, delta sets, calculation runs, analysis review
0.5.x Rust image analyzer and calculation-engine integration
0.6.x Replay, purge, crop region, and camera data management
0.7.x Runtime archive datasets and multi-engine settings
0.7.2+ Engine/tooling work resumed after or alongside 1.0.x
1.0.x Central read-only VPS viewer, push-only farm summaries, no remote control
docs/roadmap.md— version roadmapdocs/camera.md— camera subsystemdocs/dashboard.md— dashboard structuredocs/rest-api.md— API referencedocs/quickstart.md— local usagedocs/install.md— installation notesdocs/install-vps.md— central VPS viewer install notesdocs/test-vps.md— central VPS viewer test notesdocs/developer.md— developer referencedocs/devops.md— CI and release workflow
SpaghettiChef uses Jenkins-based CI.
The current pipeline verifies:
- Maven build and test execution
- runtime and API smoke lifecycle
- robustness scenarios with mixed healthy and failing printers
- JaCoCo coverage reporting
- release bundle preparation
Useful local verification commands:
mvn test
mvn clean verify
mvn -Dtest=RemoteApiServerTest test
mvn -Dtest=SdCardUploadServiceTest test
mvn -Dtest=AsyncPrintJobExecutorTest,PrintJobExecutionServiceTest testRust analyzer verification:
cd rust/img-analyzer
cargo fmt
cargo test
cargo buildMIT License
See LICENSE.








