Repository navigation
Control plane, A1 support, camera view and slicer fix: bring main up to the deployed gateway - #6
Merged
Merged
Conversation
Adds a control plane, off unless `dispatch.enabled` is set, that takes a
job from mesh to a running print with a person in the loop:
- POST /submissions accepts .stl for printers with a slicer preset; the
gateway slices with the Bambu Studio CLI, forcing the printer's nozzle
type and declared build plate, then validates and queues the 3mf.
- STATUS_SPEC v1.1 claims per printer, and three claimed verbs under
/printers/{id}/control/: snapshot (one camera frame), start_print,
stop_print. allowed_actions comes from the same gate as the 412s.
- start_print requires an approved job, a cold idle printer, a matching
declared plate, revalidation, an explicit tray per filament, and
plate_confirmed_empty by camera snapshot or in person. Verified edge
identities are required by default.
- Upload is size-verified on the printer; the job is running only when
the printer reports it. One attempt per job, never retried; an
unconfirmed or interrupted dispatch fails with its uncertainty recorded.
- /ui gains the Start and Stop flows; docs and agent rules record the
approved scope.
HT units report ids from 128, and the flat ams_mapping index used for standard units (ams_id * 4 + tray) is not known to be right for them. The gate refuses an HT tray and the page no longer offers one.
Jobs inspected before plate and slot details were recorded carried empty fields, and start_print refused them as "not a sliced .3mf". Dispatch now inspects the stored file under the claim, so it checks what will actually print and names the real reason when it refuses.
POST /printers/{id}/control/light switches the chamber LED under a claim,
in any observable state; allowed_actions advertises it from the same gate.
The /ui start panel gets a Light on/off button beside the snapshot. Homing
to raise the plate into view was declined and the reason recorded.
The first live start was uploaded and acknowledged but ignored by the printer; firmware 01.10 in cloud mode most likely refuses LAN control. Records the evidence, what users lose, a reply-capture step to confirm the cause first, the switch-over, verification order, and rollback.
The P1 and A1 series have no chamber temperature sensor, but their firmware still reports a fixed chamber_temper (5 C on the live P1S and A1). The gateway passed it through as a metric, so the dashboard showed a 5 C chamber on an open-frame A1. Key the omission on the operator-declared model, matched exactly: a real chamber can read 5 C, so the value alone is not evidence. An undeclared or unlisted model keeps whatever the printer reports, so the H2D and X1C are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The A1 has no AMS: a spool is fed by hand and its filament selected on the screen, which the printer reports as vt_tray. Dispatch only mapped AMS trays, so the A1 could not be started at all, and intake rejected its jobs because no loaded tray matched. The external spool is now read like an AMS tray (allowlisted fields only) and carried as AMS 254 tray 0 in observed.loaded_trays, so intake validation and the dispatch mapping check it the same way: material match and the spool's nozzle window. It is published as details.external_spool, apart from ams_trays. A job fed from it must be single-filament, since the start command's use_ams is all or nothing, and is sent as use_ams false with mapping [254], as Bambu Studio does. The submission page offers it as "External spool". Approved by a human on 2026-10-20 as a dispatch gate change (AGENT_RULES 1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Current Bambu Studio's A1 start gcode saves the bed mesh right after probing: "G29 ... / M400 / M500 ; save cali data". The gcode check refused every M500, so every A1 job exported from current Bambu Studio was rejected at intake. Accept exactly that M500: directly after a G29 (only M400 between), inside the machine start gcode, confirmed by the slicer's MACHINE_START_GCODE_END marker appearing afterwards. A tail scan never qualifies, and an M500 whose marker is never seen is still refused, as is every other M500. Approved by a human on 2026-10-20 as a narrowed gate (AGENT_RULES 1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A person wants to see the printer before submitting and while its job runs,
but the camera was reachable only through the claimed plate-check snapshot.
GET /printers/{id}/camera.jpg serves the chamber camera without a claim, only
when dispatch is enabled. It publishes nothing to the printer, reads the
camera at most once per printer every 2 s with the frame shared by all
viewers (failures cached the same way), and serializes camera reads with the
plate-check snapshot. Its frames carry no snapshot token, so they can never
satisfy the plate check.
The page shows it under Machine for the selected printer, off on load until
a person presses Show camera, refreshing every 2 s and pausing while the tab
is hidden.
Approved by a human on 2026-10-21, amending AGENT_RULES rule 3.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Bambu Studio CLI does not resolve `inherits` (or the newer `include` templates) for a settings file outside its bundled profiles. The slicer copied the machine preset into the job dir with only the child's own keys, so everything the parents define was silently replaced by CLI defaults: an A1 slice came out with a 200 x 200 bed, a two-line G28 start gcode instead of the A1's (no wipe, no bed leveling, no purge) and generic 200 C PLA. The 2026-10-05 P1S test job carried the same generic start. Fold each preset's inherits chain and include templates into one self-contained file, child values winning, for the machine, process and filament alike. A fixed A1 slice now matches a Bambu Studio export apart from version differences. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… who The not-signed-in and no-identity warnings stay: those change what a submission means. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The page is embedded in the dashboard's 3D Printers panel; opened on its own under the edge prefix it now redirects there instead of being a second, full-page copy. Direct gateway access (no prefix) still serves it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The camera sits in a 4:3 frame on the left of the Machine panel with the detail tiles to its right (stacked, capped at 320 px, on narrow screens). The frame keeps its size whether the camera is on or off; it shows "Camera off" until a person presses Start camera. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed in through the dashboard, the edge identity is what gets recorded, so the read-only "Signed in as" field only restated the sign-in. Visitors who are not signed in still type a name. The camera frame grows from 280 to 420 px (480 px cap when stacked). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rame With the live camera view on the page, the start panel's "Take snapshot" step only repeated what the person had just looked at. A camera start_print without a snapshot_token now has the gateway capture the frame itself, under the claim, at the moment start is pressed, and keep its hash, time and image with the job -- a fresher record than a snapshot taken minutes earlier. If the camera delivers no frame the start is refused (502) and nothing is uploaded; a snapshot_token from /control/snapshot is still accepted. The person's plate_confirmed_empty statement is unchanged. The start panel loses the snapshot box and button and points to the camera view above; the light button stays. Approved by a human on 2026-10-21 as a dispatch gate change (AGENT_RULES 1, 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ecklist - The printer dropdown, Start camera and the light share one bar; the "Machine" heading and "Target" label are gone. The light takes a claim only for the switch (or uses the start panel's) and gives it back. - Artifact and Result become one Submission section: file, material, name and Submit on the left with a small preview of the thumbnail the slicer embedded (.3mf plate_N.png or the .gcode thumbnail block, read in the browser); the checklist on the right, always shown, pending until the file is submitted. - The external spool's remaining percentage is dropped: a hand-fed spool has no sensor and the A1's 0 is a placeholder, not "empty". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cyrilcaoyang
marked this pull request as ready for review
October 21, 2026 03:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The deployed gateway runs this branch, not
main. This PR bringsmainup to what is deployed: the human-approved control plane (2026-10-04), STL slicing, the chamber light, planning docs, and the work done 2026-10-20/21 to add and print on the Bambu A1.What's in it
Control plane and slicing (2026-10-04/05): STATUS_SPEC v1.1 claims,
start_print,stop_print, camera snapshot and chamber light, all gated inbambu_server.dispatch. Headless Bambu Studio slicing. AMS HT trays are refused until their tray index is verified. Dispatch re-reads the artifact instead of trusting intake facts.Approved gate changes (each recorded in
AGENT_RULES.md,AGENTS.mdanddocs/CONTROL_PLANE_DESIGN.md):vt_tray, id 254) as a mapping target for printers without an AMS. It gets the same material and nozzle-window checks, is single-filament only, and is sent asuse_ams: falsewith mapping[254].M500accepted only directly afterG29inside the machine start gcode, confirmed by the end marker. Every otherM500is still refused.GET /printers/{id}/camera.jpg: no claim, no command, one shared read per printer every 2 s, never plate-check evidence. It amends rule 3.start_printcaptures and records its own frame under the claim when start is pressed, and refuses with 502 if the camera delivers none.Fixes:
inheritsandincludepresets. Before this, CLI slices silently got a 200 × 200 bed, a genericG28start gcode and generic temperatures. The 2026-10-05 P1S test job carried the same broken start.Page:
/bamburedirects to the dashboard panel.Hardware results (2026-10-21, A1 in LAN Only + Developer Mode)
adptor.gcode.3mf(external spool, stockM500): upload verified, and the printer confirmed RUNNING 8 s after the start command. It printed to the end, but the part detached (no brim, a first layer of thin walls only). The gateway reports "finished" for a failed print; it has no failure detection.3DBenchy(external spool, flattened-preset slice, textured plate): RUNNING confirmed 12 s after the command, and it printed end to end, confirmed by camera snapshot.Test plan
uv run pytest -q: 243 passed (fake backends only)ruff check .is cleanstart_print→ RUNNING within the confirm timeout (twice)stop_printpartway through a print. Never exercised yet.🤖 Generated with Claude Code