Skip to content

Printer Control

Every printer card on the dashboard exposes the in-app equivalent of the buttons on the physical printer's touchscreen. This page is the catalogue: what each button does, which BamDude permission gates it, and which MQTT command actually goes out the wire.


What It Is

A printer card is a thin client that sits in front of PrinterManager (backend/app/services/printer_manager.py) and talks to the printer over MQTT through BambuMqttClient. The card surfaces:

  • Status (idle / printing / paused / error) and live telemetry (temps, fans, AMS)
  • Print actions (start / pause / resume / stop / clear plate / skip object)
  • Hardware controls (chamber light, bed jog, full home, print speed, airduct mode)
  • Smart-plug actions (power on / off via the bound plug)
  • Debug helpers (force MQTT refresh)

Most actions are gated by printers:control. Two subsets carve off lower-privilege actions: printers:clear_plate (just the post-print "next job ready" handshake) and printers:read (status + object lists, no commands).


Start a print from the card

Drag a sliced .gcode or .gcode.3mf file onto a printer card or click the green Print button. The file is uploaded to your library, the print modal opens with that printer pre-selected, and the job is dispatched through the standard print queue.

The card also shows a red "Printer busy" overlay when you drop on a non-idle printer, so you don't accidentally interrupt a running job. See Print Queue for what happens after the dispatch.

Permission

printers:control. The library upload itself also checks library:upload.

Nozzle Offset Calibration (dual-nozzle only)

On the H2D, H2D Pro, H2C and X2D, the print dialog shows a "Nozzle Offset Calibration" toggle — on by default, matching Bambu Studio. It controls whether the printer runs its nozzle-offset calibration routine before the print starts.

Previously this calibration was always skipped, with no way to enable it — and, just as importantly, no way to keep it deliberately off. That off case matters for diamond-nozzle setups, which must not run the routine.

The toggle only appears on dual-nozzle printers. Single-nozzle machines always skip the calibration regardless of any setting. Your choice is remembered per queue item and applied on every dispatch path (queue, drag-and-drop, re-print).

Pause / Resume

Button When visible Endpoint What it sends
Pause State = printing POST /api/v1/printers/{id}/print/pause MQTT pause
Resume State = paused POST /api/v1/printers/{id}/print/resume MQTT resume

Both actions show a confirmation dialog to prevent fat-finger interrupts.

Stop print

POST /api/v1/printers/{id}/print/stop — sends MQTT stop and also marks the printer as user-stopped in the dispatch tracking dict. That second step is important: without it the HMS heuristic in _dispatch_archive_update would later misclassify the cancel-sequence HMS code (e.g. H2D's module-0x0C) as a real "Layer shift" failure. Stopping a print cannot be undone — the print restarts from the beginning if you re-queue it.

Skip object

For multi-object plates: skip a single object that's failing while letting the rest finish.

GET  /api/v1/printers/{id}/print/objects     → list objects with skip status
POST /api/v1/printers/{id}/print/skip-objects → skip selected IDs

The list comes from the active 3MF (subtask_name), read from the G-code's own ; model label id: header where present — that is the list the firmware works from, and it names every copy on the plate. slice_info.config is only the last fallback: newer OrcaSlicer records just the original there when a plate holds several copies of one model. Since 0.5.3 the list is also filled when BamDude joins a print already under way — a restart mid-plate used to leave it empty, and the Skip button dark, until somebody opened this dialog. If it is still empty, pass ?reload=true and BamDude pulls the 3MF off the printer's FTP and re-parses it — supports multiple filename variants ({name}.3mf, {name}.gcode.3mf, with-spaces and underscored).

Wait for layer 2

The printer firmware refuses skip commands until the first layer is laid down. The skip modal shows a yellow banner on layer 0/1.

Match printer object IDs

The IDs shown in the BamDude modal match the IDs on the printer's touchscreen plate visualisation — that's how you identify which physical part is which.

Also in the Telegram bot

The same action, with the same marker placement, is available from the bot — useful precisely when you are not at the computer. See Telegram Bot.

Clear plate

After a print finishes (or fails) and there are queued jobs waiting, the Clear Plate & Start Next button appears. Clicking it calls:

POST /api/v1/printers/{id}/clear-plate

This does not send an MQTT command to the printer — it just flips a server-side awaiting_plate_clear flag, which unblocks the queue scheduler so the next start command goes out. The printer accepts the new print and overrides its FINISH / FAILED state automatically.

Accepted printer states: FINISH, FAILED, IDLE. The IDLE case covers Auto-Off cycles — when the printer was powered off via smart plug after a job, the persisted awaiting_plate_clear flag is still set when it boots back into IDLE, and the operator still needs to acknowledge the cleared plate.

Distinct permission

Clear-plate uses printers:clear_plate — a more granular permission than printers:control. You can grant a tech the ability to OK the next job without giving them stop / pause / chamber-light access.

Clear HMS errors

POST /api/v1/printers/{id}/hms/clear — sends clean_print_error via MQTT and clears the HMS list from the card immediately. Useful after a cancel that left stale print_error codes behind.


Printer Settings Dialog

A per-printer dialog that mirrors Bambu Studio → Print Options + Printer Parts. Open it from the kebab menu on a printer card → Printer Settings.

Four tabs:

  • Print Options — every toggle BS exposes for the running printer: AI detections, sensors, plate behaviours, sound, auto-recovery. Gated to exactly what the printer reports it supports (see Visibility).
  • Safety (X2D / P2S) — Open Door Detection + Idle Heating Protection, mirroring BS's Safety Options dialog. Only appears on models that expose safety options.
  • Printer Parts — read-only view of installed nozzle(s) (type, diameter, flow rate). Editing parts on-printer is reserved for a future phase; today the API returns 409 parts_not_editable if a write is attempted.
  • Add-ons — the printer body plus every connected accessory (AMS units, filament buffer, exhaust fan, …), mirroring BS's Update Device view.
Group Setting Values MQTT
AI detections AI monitoring (legacy toggle) On/Off + Low/Medium/High xcam_control_set (printing_monitor)
Spaghetti detector On/Off + Low/Medium/High xcam_control_set (spaghetti_detector)
Pile-up at purge chute On/Off + Low/Medium/High xcam_control_set (pileup_detector)
Nozzle-clumping On/Off + Low/Medium/High xcam_control_set (clump_detector)
Air-printing On/Off + Low/Medium/High xcam_control_set (airprint_detector)
First-layer inspector On/Off xcam_control_set (first_layer_inspector)
Sensors FOD check (foreign-object) On/Off xcam_control_set (fod_check)
Displacement detection On/Off xcam_control_set (model_movement_check)
Filament tangle detect On/Off print_option (filament_tangle_detect)
Nozzle-blob detect (legacy) On/Off print_option (nozzle_blob_detect)
Nozzle-clumping (smart, 3-mode) Auto / On / Off print_option (nozzle_blob_detect_v2)
Air-print detection (sensor) On/Off print_option (air_print_detect)
Plate Build-plate position detection (legacy) On/Off xcam_control_set (buildplate_marker_detector)
Build-plate marker/type detect On/Off xcam_control_set (buildplate_marker_detector)
Plate alignment check On/Off xcam_control_set (plate_offset_switch)
Chamber Purify air at print end Off / Inside / Outside print_option (air_purification)
Misc Auto recovery on step loss On/Off print_option (auto_recovery)
Prompt sound On/Off print_option (sound_enable)
Camera snapshot enable On/Off ipcam_cap_pic_set
Store sent files on external storage On/Off system (print_cache_set)

A few options are mutually exclusive (BS parity), so you only ever see one of each pair: the legacy build-plate position toggle vs the newer marker + alignment group; the legacy nozzle-blob on/off vs the smart 3-mode nozzle-clumping switch; and the legacy AI monitoring toggle vs the newer per-type AI detections (spaghetti / pile-up / clumping / air-print). The xcam_control_set module names above are the firmware's own wire names — several differ from BamDude's internal keys, and are mapped on the way out so the toggles actually apply. Open Door Detection used to live here; it now sits in the Safety tab on X2D / P2S (and stays in Print Options for the X1 family) — see below.

Visibility — what shows up depends on the printer

Each row shows only if the printer reports it supports that option — resolved the same way Bambu Studio does, from the live capability flags in the MQTT push (fun / fun2 / cfg / home_flag bitfields, the xcam message, and the support_* booleans), not from a hardcoded per-model table. So the list matches the printer — and BS — on every model, and stays correct as firmware evolves.

In practice this means, for example:

  • The AI detections (spaghetti, pile-up, nozzle-clumping, air-printing) appear on camera-AI machines that advertise them via the fun bits — the X2D and H2 family — and are correctly absent on the P1 / A1 series (which report no xcam.cfg, so they have no AI at all).
  • Foreign-object and displacement detection follow the same fun2 support bits.
  • Filament tangle, nozzle blob and notification sounds come from home_flag bits, so they show on whichever models actually expose them (e.g. the A1 mini reports tangle + blob; the P1S doesn't).
  • Store sent files on external storage shows only where the firmware advertises the feature (X2D), and is hidden on printers that have storage but don't expose it (P1S).
  • Purify air follows its fun2 bit; Open Door Detection follows fun bit 12 and the model's support_safety_options config (Print Options for the X1 family, the Safety tab for X2D / P2S).

If a printer hasn't sent its full status yet (the first moment after connecting), BamDude falls back to a conservative per-family guess until the real flags arrive.

State source of truth — the printer

BamDude does not persist a "desired state" on its side. The state shown in the dialog comes from the printer's MQTT status push. When you toggle a row, BamDude publishes the matching MQTT command and starts a 3-second hold (printer_settings_hold per-key) so the row doesn't flicker between optimistic and confirmed values — same pattern as the AMS Settings dialog.

Because that MQTT round-trip takes a moment, the control you touched freezes and shows a small "waiting for confirmation" spinner until the printer confirms, then the value refreshes in the open dialog — it never closes and reopens. You can't fire the same toggle repeatedly while it's still applying.

If the printer drops a setting (factory reset, firmware-update wipe), BamDude reflects that — there's no reconciliation. Open the dialog again and re-toggle.

Safety tab (X2D / P2S)

Printers that advertise support_safety_options (currently the X2D and P2S) get a Safety tab next to Print Options, mirroring BS's Safety Options dialog:

  • Open Door Detection — what the printer does when the enclosure door opens mid-print: Off / Notification / Pause printing. Read from cfg bits 20-21, written via the system set_door_stat command. On these models the control lives here instead of in Print Options.
  • Idle Heating Protection — automatically stops heating after 5 minutes of idle. Read from cfg bits 32-33 (a third "unavailable" state greys the toggle while the printer's heating-maintenance function is active), written via set_against_continued_heating_mode.

Permissions and audit

The kebab item only appears for users with the printers:update permission. The same permission gates the POST /api/v1/printers/{id}/settings endpoint.

Every applied change writes one row to the printer_setting_audit table (m061) — (printer_id, user_id, tab, action, payload_json, sequence_id, result, error_message, created_at). No in-UI viewer yet; query the table directly if you need to answer "who turned spaghetti-detection off last Thursday?"

On-device calibration is separate

Bed leveling, resonance, motor noise and the other machine self-calibration routines aren't print-option toggles — they're long-running on-device routines under their own kebab entry Calibration, documented next.


Device Calibration

The printer's own on-device self-calibration routines — bed leveling, resonance/vibration, motor noise, and, on newer hardware, nozzle offset, high-temp bed leveling, micro-lidar and nozzle-clumping detection. This is the same set Bambu Studio exposes under Device → Calibration: not filament tuning (that's the wizard below), but the machine's own calibration steps that run on the printer with no sliced g-code involved.

Open it from the kebab menu on a printer card → Calibration.

What's available depends on the model

BamDude shows only the calibrations your specific printer model and firmware actually support — resolved exactly like Bambu Studio:

Calibration Typically available on
Auto Bed Leveling almost every model
Vibration Compensation every model
Motor Noise Cancellation read live from the printer (P1S, A1 series, X2D, …)
Nozzle Offset dual-nozzle / X2D / H2 series
High-Temp Bed Leveling X2D / H2 series / P2S / A2L
Micro Lidar X1 series
Nozzle Clumping Detection P2S / H2S

The availability isn't a hand-maintained table. BamDude merges two sources — hybrid gating, mirroring Bambu Studio:

  1. Base defaults — byte-for-byte copies of Bambu Studio's own per-model config files (resources/printers/<model>.json), shipped under backend/app/data/printers/. Re-syncing them is a folder re-copy + git diff against a fresh Bambu Studio checkout.
  2. Live capability flags — the printer's own MQTT status flags, which override the defaults. Motor Noise Cancellation in particular is a live signal, not a static per-model flag: some machines advertise it in the home_flag bitfield (P1 / X1 series), others in the fun bitfield (H2 / X2 series), so BamDude surfaces it wherever the printer reports it — exactly as Bambu Studio does.

Live progress

Pick the steps you want and press Start Calibration. The dialog then stays open and shows the printer's own stage-by-stage progress live — the same stage list Bambu Studio renders — each step ticking from pending → running → done until the routine completes.


Filament Calibration

A wizard that mirrors Bambu Studio → Calibrate → Pressure Advance / Flow Rate / Towers without leaving BamDude. Open it from the kebab menu on a printer card → Filament Calibration. History review lives on a sibling kebab entry → Calibration History.

What's calibrated

Mode Path Output
PA Line Manual: flat one-layer block of stepped-K rows (slow / fast / slow extrusion in each) + numbered side tab — pick the cleanest row, K = label next to it. Visually like PA Pattern but with straight lines instead of V-shaped walls pa_k_value per (filament, nozzle, extruder)
PA Tower Manual: stepped vertical tower — measure the height (mm) where corners look cleanest, K = Start + (Step × height) pa_k_value per (filament, nozzle, extruder)
PA Pattern Manual: comb of V-shaped walls at stepped K values + numbered digits in a glyph tab — pick the cleanest pattern column, read the K from its label pa_k_value per (filament, nozzle, extruder)
Auto PA X1 / X1E / H2D Pro: lidar scans + reports K/N same (pre-filled save dialog)
Flow Rate Manual: 9-block coarse (−20…+20 %) → 7-block fine refinement flow_ratio per combo
Auto Flow Rate X1 lidar variant same
Temp / VolSpeed / VFA / Retraction Tower Manual print only; read result with your eyes, enter in slicer no DB row written

Per-model capability gating

Per-model rules — auto paths need lidar + firmware support flag; manual paths universally available.

Path X1 family P1 / P2 / X2D A1 / A1 Mini H2D / H2D Pro
Manual PA / Flow Rate / Towers yes yes yes yes
Auto PA (lidar) yes — — yes (Pro)
Auto Flow Rate (lidar) yes — — yes (Pro)
Dual-extruder (per-extruder cali) — — — yes

Slicer-sidecar gating (0.4.5)

Bambu Studio's calibration wizard always runs full slicing — even modes that look "pre-sliced" (PA Pattern, Flow Rate, Auto PA) load geometry from resources/calib/ as scaffolds, then BS applies the active printer / process / filament preset plus per-mode g-code injection through Plater::calib_* / CalibUtils::*. BamDude mirrors the same 12 BS files under backend/app/data/calib_assets/ but reaches the same slicing step through our server-side slicing sidecar (OrcaSlicer / Bambu Studio API).

So every Filament Calibration mode needs a connected sidecar. To keep that visible:

  • The Filament Calibration and Calibration History kebab entries on the printer card are hidden when "Server-side slicing" is off in Settings (General → General).
  • If a direct API call slips through, POST /printers/{id}/calibration/sessions returns 409 {detail: "slicer_sidecar_required"} for any manual mode.
  • Auto modes (Auto PA / Auto Flow Rate on lidar-equipped X1 / X1E / H2D Pro) are printer-side only — they go through MQTT extrusion_cali_start / flow_rate_cali_start without any local slicing. But since the rest of the wizard depends on the sidecar, the entry points are gated together.

PA Tower (Phase 1), PA Pattern (Phase 2), and PA Line (Phase 9) are wired end-to-end as of 0.4.5 — pick any of them in the wizard, the slicer sidecar bakes the pattern, BamDude FTPs the gcode to the printer, runs it, and surfaces the manual-save dialog when finished. The remaining manual modes (Temp / Retraction / VFA / Volumetric Speed Towers, Flow Rate) cycle through verification (downloads a sliced 3MF for desktop comparison) before flipping to production — that staged rollout is Wave 2 of the calibration roadmap.

The wizard's preset page includes the same PrintOptionsPanel + SwapMacrosPanel you get on the regular print dialog. It reads your saved per-printer-model preferences (PrintModal and the calibration wizard share the storage key), so settings tuned once for a model — e.g. always-on swap macros on A1 plate-change, or layer inspection on X1E — apply automatically to calibration prints too. Saved preferences upsert on each successful start. Calibration-tuned defaults: bed_levelling=true, flow_cali=false (otherwise the printer's pre-print flow-cali would overwrite the gcode's M900 K sweep and mask the test), swap macros opt-in. MQTT-action macros (P1S chamber light on/off) fire automatically through the standard print_started / print_finished event hooks — no per-job toggle.

State + persistence

  • BamDude row written to filament_calibration keyed by (printer_id, filament_id, nozzle_diameter, nozzle_volume_type, extruder_id) since m063 — per-printer-instance, not per-model. Two X1Cs in the same farm carry independent K values for the same material.
  • The printer is the source of truth. BamDude's table is a cache. Whenever BamDude reads extrusion_cali_get it mirrors every visible profile into the cache by stable identity (name + filament_id + pa_k_value) — new rows arrive inactive; you promote one row per combo from the History modal.
  • Sync runs automatically on every MQTT (re)connect and whenever the printer's live K-profile list actually changes (hash-diff filtered so it doesn't fire on every push_status broadcast). The manage / history dialogs still trigger fresh pulls on demand.
  • Every cache row carries the printer-side nozzle_id (HS00-0.4, HH00-0.6, …) so you can see which physical nozzle each calibration was captured on. On P1S / A1 / A1 mini — where the per-profile id isn't shipped — BamDude derives it from the device-level nozzle hardware state.
  • is_active=True per combo is enforced by a partial unique index. Promoting a row flips its siblings to inactive.
  • Spool ↔ K-profile links (m064) are thin: a spool_k_profile row carries only (spool, printer, extruder, filament_calibration_id). One hundred PETG spools sharing the same calibration collapse to one cache row + many links instead of duplicated K data.
  • Calibration assets are mirrored from BS resources/calib/ (AGPL-3.0) under backend/app/data/calib_assets/ — 12 files total (3MF / STL / STEP scaffolds; see Slicer-sidecar gating above for why all modes still need a sidecar). PA Line range: 0.0–0.1 step 0.002 (50 lines). Flow Rate coarse: [-20, -15, -10, -5, 0, 5, 10, 15, 20] %; fine: [-5, -2, 0, 2, 5, 10, 15] %.

Apply path on a real print

background_dispatch calls the unified apply_active_calibration_to_slot helper for every AMS slot the job will use. Resolution order: explicit spool→calibration link → active filament_calibration row by combo. The helper then re-matches the cached row against client.state.kprofiles by stable identity (name + filament_id + pa_k_value) to find the LIVE cali_idx — the printer reorders slots when you delete a neighbour, so the stored number is a hint only — and fires extrusion_cali_sel(ams_id, slot_id, cali_idx) before the print starts.

The same helper now runs from the post-RFID-refresh path, the tray-tag drift detect, the auto-spool tagger, and both inventory + Spoolman slot-assign endpoints — six call sites collapsed onto one. Closes the silent-drift gap where the firmware was falling back to the default profile after RFID re-taps, slot reassignments, or restarts even though your SpoolAssignment row was intact.

External-source prints (BS, printer screen) still benefit: the slot binding persists on the printer until explicitly changed, so the last extrusion_cali_sel BamDude fired stays in effect.

History modal

Two sections side by side:

  • BamDude history — filament_calibration rows grouped by nozzle. Per-row actions: Set Active (flips siblings + fires extrusion_cali_sel), Delete. Active row marked with green ring + checkmark.
  • Printer-side history — 16-slot view pulled via extrusion_cali_get. Refresh button forces a re-pull for a given nozzle diameter.

Resume banner

If you close the wizard mid-flow (after the print finished but before you saved), reopening the wizard shows a yellow banner with Resume / Discard for the in-flight session.

Permissions and audit

printers:update gates the wizard entry and all mutation routes. Every action writes a row to calibration_audit — (printer_id, session_id, action, payload_json, sequence_id, result, error_message, created_at). Actions: start_session / save_result / set_active / delete / cancel, plus the legacy K-profiles UI page mutations from 0.4.5: kprofile_add / kprofile_edit / kprofile_batch_add / kprofile_delete. No in-UI viewer yet; query the table directly.

Edit-Save with no printer-relevant change skips the printer

Since 0.4.5 the K-profiles edit dialog diffs name / k_value / filament_id / nozzle_id / nozzle_diameter against the loaded row before publishing. Identical → only the note (BamDude-local) is saved; no extrusion_cali_set fires. Stops the printer from regenerating setting_id on every Save click, which used to drift the cache row.

What's intentionally NOT in BamDude (yet)

  • PA range customization — start/end/step are fixed to BS defaults. If you need a different range, calibrate in BS itself and import the value.
  • External spool calibration — virtual tray tray_id >= 0x10000 is disabled for the auto path; the manual path allows it but tray binding may not survive printer reboot.
  • Tower-mode result entry in BamDude — tower modes start the print and finish. Read the result with your eyes, enter it in your slicer's filament profile. (BS does the same.)

Bed Jog (Z-Axis)

Move the build plate up or down by a fixed step.

POST /api/v1/printers/{id}/bed-jog?distance=N
Param Validation
distance Non-zero, |distance| <= 200 mm

The force parameter was removed in 0.4.7. It wrapped the move in M211 S0 … M211 S1 — a command form that does not exist in Bambu's firmware dialect (there, bare M211 S means push the endstop state and M211 R means pop it), and the UI sent it on every jog, so every manual move ran without the soft endstops being explicitly enabled. A stray ?force=true from an old client is ignored.

Step selector in the popover: 1 / 10 / 50 mm. Only enabled when the printer is not running a print.

The same axis is also in the Motion Control window below, together with X, Y and the extruder. Both go through one implementation, so the direction handling and the endstop sequence cannot drift apart.

G-code sent

What Bambu Studio's own jog sends over the same MQTT gcode_line channel (DevAxis::Ctrl_Axis). Until 0.5.2 the sequence matched but the feedrate did not — BamDude drove Z at 600 while Studio drives it at 900:

M211 S              ; remember the current soft-endstop state
M211 X1 Y1 Z1       ; explicitly ENABLE all three
M1002 push_ref_mode
G91
G1 ZN F900
M1002 pop_ref_mode
M211 R              ; restore the remembered state

Enabling the endstops is the point: Bambu's own sliced start G-code turns them off (the A1 machine template ends with M211 X0 Y0 Z0 and never restores it; H2D re-enables only M211 Z1), so a printer sitting idle after a print usually has them disabled. Bambu Studio re-enables them before every manual move for exactly this reason.

Not-homed warning

After a print completes, the Z axis usually isn't referenced. Trying to jog shows a Bambu-Studio-style modal:

Choice Action
Auto Home Runs the printer's full auto-home sequence and dismisses the dialog
Cancel Closes the dialog, no command sent

Since 0.5.2 whether the printer is homed is read from the printer (home_flag), not remembered per browser session. The old note was wrong in both directions: homing from the machine's own screen still produced the warning, and a printer that lost its home after BamDude homed it did not.

The Move anyway button was removed in 0.4.7 — it was the path that drove the plate with the soft endstops bypassed. BamDude now asks you to home first, then jog. This is deliberately stricter than Bambu Studio, which sends the move and only afterwards suggests recentering: Studio is a window in front of the machine, while this page can be open on a phone in another room.

Travel limits are not guaranteed

BamDude enables the soft endstops before every jog, but Bambu firmware has been observed running a move past the limit anyway, and it reports no axis position — so the move cannot be clamped client-side either. Keep distances small (≤10 mm) until the plate is in a known-safe position and watch the printer.


Home Axes

POST /api/v1/printers/{id}/home-axes?axes={z|xy|all}

The axes parameter is kept only for backward compatibility — every call sends a bare G28, regardless of what you passed. The reason is upstream issue #1052: on H2C the bed homes by moving up toward the top endstop, and a bare G28 Z skips the toolhead-park step that a full G28 runs first. The result was bed crashing into the toolhead. So BamDude unconditionally sends G28 and lets the firmware run its safe park-XY-then-home-Z sequence.

Invalid axes values still return 400 so typos surface.



Motion Control

Everything that moves, in one window — opened from the temperature row on the printer card.

The toolhead

A round pad, as in Bambu Studio: the outer ring is 10 mm, the inner ring is 1 mm, and Home sits in the middle.

Why fixed steps and not a distance field

Newer printers take these moves over a command (xyz_ctrl) that carries a direction and a coarse/fine flag — and nothing else. On those machines 3 mm and 9 mm are literally the same request, as are 10 mm and 200 mm. A free number box would promise a precision the printer never receives. Older machines still get the G-code form with the exact distance; BamDude picks per printer, the way Studio does.

Which way is "up" does not depend on your model. On an A1 or A1 Mini the Z axis carries the toolhead rather than the bed, so the same command means the opposite motion — BamDude flips it for you, and every button sends the same number for every machine.

The nozzle-bed gap

The same four steps as the bed jog above, laid out either side of the label.

The extruder

Push filament through the nozzle or pull it back, 10 mm at a time. On dual-nozzle machines, pick Main or Auxiliary first — the picture shows which one is selected and whether it has filament loaded.

Below 170 °C the extruder will not move

Bambu Studio's own threshold, and it is not a formality: cold extrusion grinds a flat onto the filament and packs the shavings into the gear teeth. The buttons stay disabled and say what temperature they are waiting for. On dual-nozzle machines each extruder is checked separately — a warm nozzle does not vouch for its cold neighbour.

Release motors

Drops the steppers (M84) so the toolhead can be pushed by hand. This drops whatever the Z axis was holding — the bed on most machines, the toolhead on a bed-slinger.

What it refuses

Situation What happens
A print is running or paused Everything is disabled, and the API refuses too (409)
X or Y not homed Those moves are refused — this is Studio's own rule, which checks before moving
Z not homed Also refused, which is stricter than Studio: it sends the Z move and only afterwards suggests recentering
Nozzle below 170 °C The extruder is refused (409)
No hotend detected That extruder is refused. Printers that cannot detect a hotend at all (A and P series) are unaffected — "cannot tell" is treated as fitted, as Studio treats it
POST /api/v1/printers/{id}/jog?axis=x|y|z|e&distance=N&extruder_index=0|1
POST /api/v1/printers/{id}/disable-steppers

Both gated by printers:control.


Timelapse: what BamDude checks before it promises one

The timelapse tick used to be sent to any printer, including one with no card in it — the request went nowhere and the print finished with no video and no explanation. Two checks now stand where Bambu Studio puts them.

When you choose printers, a machine that cannot record is named in the dialog, with which of three problems it has: no SD card, an unreadable one, or a read-only one. Those are three different situations — a card sitting in the slot and refusing to be written is not an empty slot.

A card is not always needed

Printers with internal timelapse storage, or with a timelapse kit fitted, record without one — so neither is asked about the card at all. Which machines those are comes from the printer itself, not from a list of model names.

When a queued print starts and the printer has run out of room, that printer's queue pauses instead of quietly dropping the recording. Deleting the video you asked for is a decision nobody was present to make.

It never pauses on a number nobody reported

A printer that has not published its free space does not pause anything. Stranding a farm on a figure that was never measured would be worse than the missing video this protects.

Where the printer keeps timelapses itself, the print dialog also offers to free space by dropping the oldest recording — the same escape hatch Bambu Studio gives, and nothing is deleted without that click.


Temperature Control

Set the nozzle, the bed and the chamber — not just read them. Opened from the thermometer button in the temperature row.

Type a value, step it with the arrows, or turn a heater off outright. Dual-nozzle machines get both nozzles, addressed separately.

The limits are your printer's

Each field shows the range that machine actually accepts, and it is not the same everywhere:

Nozzle 20–300 °C, or whatever range the printer reports
Bed up to 120 °C — but see below
Chamber 60 °C on an X1E, 65 °C on the H2 family

An X1 on 220 V mains accepts a lower bed temperature

110 °C instead of 120. It reads backwards until you take it as a fact about the heating element rather than about available power. BamDude reads the mains voltage from the printer and adjusts the limit, as Bambu Studio does.

Anything above the maximum is trimmed to it rather than rejected — again, Studio's behaviour.

Off is a real value

Zero is exempt from the range on purpose. A bed whose minimum is 20 °C can still be switched off, which is the whole point of the button.

What it refuses

  • A chamber that is only measured cannot be commanded. The X1C and P2S report a chamber temperature they have no heater for; the dialog says so instead of failing silently.
  • An extruder with no hotend fitted will not be told to heat, on machines that can detect that.

No mid-print confirmation here

Unlike the fan controls, this dialog asks nothing extra during a print. Adjusting a temperature mid-print is ordinary tuning, and Bambu Studio gates none of the three on print state.

POST /api/v1/printers/{id}/temperature?part=nozzle|bed|chamber&target=N&extruder_index=0|1

Gated by printers:control.


Chamber Light

POST /api/v1/printers/{id}/chamber-light?on={true|false}

Toggles the chamber LED via MQTT. Optimistic UI update on click, toast confirmation on round-trip success.

H2D dual lights

On H2D, both chamber lights are controlled together — there's no per-light toggle in the firmware.


Airduct Mode (P2S / X2D / H2 series)

Available only on printers with an active airduct (P2S, X2D, H2D, H2C, H2S). The card shows an airduct badge in the controls row; printers without an airduct hide it entirely.

Mode Icon Use With
Cooling PLA / PETG / TPU — filters and cools the chamber
Heating ABS / ASA / PC / PA — circulates and heats the chamber, closes top exhaust flap

Switching mode goes out as the MQTT set_airduct command (BambuMqttClient.set_airduct_mode). The current mode is reflected back via airduct.modeCur in the printer's status push — the badge updates as soon as the printer confirms.


Change print speed mid-job without leaving the printer card.

POST /api/v1/printers/{id}/print-speed?mode=N
Mode Preset Speed Use For
1 Silent 50% Night prints, noise-sensitive rooms
2 Standard 100% Default slicer speed
3 Sport 124% Simple geometry, time-pressure
4 Ludicrous 166% Maximum speed

The badge in the controls row shows the current speed percentage and is dimmed when no print is active.


Fans and the air duct

Live fan badges in the controls row, showing the speeds the printer reports — and, where the printer allows it, a control for each.

Every fan the printer reports appears, on every model. Older machines (P1S, P1P, X1C, A1) do not describe an air duct at all, so BamDude builds the same picture from the speeds they do report — which is exactly what Bambu Studio does before drawing its own panel. Those printers used to show three read-only numbers; they now have working fan control.

A fan that does not exist does not appear. Whether a machine has an auxiliary or chamber fan is answered by the printer's own capability flags, not by a list of model names — an A1 Mini has part cooling only, and reports a speed for the other two anyway, so the reported speed cannot be the evidence.

What the air-duct mode does to each fan

On machines with an air duct (P2S, X2D, H2 family) the active mode decides, per fan, one of three things. The badge shows which:

Adjustable the mode hands this fan to you
Off the mode holds it off — the printer would accept a command for it and ignore it
Auto the firmware is driving it

The difference between the last two matters: one you can change by changing the mode, the other you cannot. Asking for a speed on either is refused (409) with a message that says which of the two applies.

Setting a speed

The menu on a badge offers the steps the printer actually has. Bambu Lab printers count in ten gears, so the speeds are 10 % apart — anything in between would be resolved on arrival to something you did not choose. Turn off is its own entry, shown when the fan is running.

POST /printers/{id}/fan-speed?part_id=<n>&percent=<0-100>, gated by printers:control. An id the printer never reported is refused (400) rather than sent.

Changing a fan while a print is running asks first, as Studio does, and the request is refused without that acknowledgement — so an automation cannot quietly do what a person is warned about. You are asked once per printer per browser session.

The air-duct window

Machines that report air-duct modes get a control next to the badges that opens the whole thing: the mode, filtration, and every fan with a − / + adjuster.

  • The modes offered are the ones your printer lists. Not a fixed set — a machine that reports two gets two.
  • The mode cannot be changed while a print is running. The buttons say so rather than failing when pressed: the loaded material is what the mode was chosen for, and Studio refuses this outright rather than warning.
  • Filtration appears where the hardware has it, and only on the cooling mode. It redirects one fan to filtering chamber air, which costs cooling — so turning it on mid-print asks first. Turning it off gives the cooling back and asks nothing.

Fan names come from your printer, not from a table

The same part id is a different fan on different models — part 10 is the left auxiliary on a P2S and the right one on an X2D, and on the X2D it is named differently in cooling and in heating mode. The names come from the Bambu Studio printer definitions BamDude ships, so a P2S says Right Auxiliary Fan rather than just "Auxiliary".


Power Controls (smart plug)

If a smart plug is bound to the printer:

Action What happens
Power On Plug turns on. The printer boots and reconnects to MQTT a few seconds later.
Power Off Plug turns off. BamDude does not send an MQTT shutdown command — it just cuts power.

Auto-power-off is configured per printer: after a print completes and the bed/nozzle drop below a configurable cooldown threshold for a configurable wait time, the bound plug is turned off. See Smart Plugs for the threshold + wait-time fields and for the integration types (Tasmota / HA / REST / MQTT).

BamDude does not have a "soft shutdown" MQTT command

There is no MQTT command that cleanly shuts a Bambu printer down. Power-off goes through the smart plug. If you don't have one, the only way to shut down is the printer's own front-panel button.


Force Refresh (MQTT pushall)

POST /api/v1/printers/{id}/refresh-status

Asks the printer to re-broadcast its full status (MQTT pushall). Useful when a value on the card looks stale and you don't want to fully reconnect — full reconnect tears down the existing MQTT/FTP session and is slower. The endpoint is in the printer card's three-dot menu.

For a heavier reset, the stop / start of printer_manager.ensure_fresh_connection_for_printer runs automatically before any control command — that re-establishes a stalled MQTT connection without operator intervention.


Maintenance Mode

Take a printer out of service without deleting it — for a nozzle swap, a belt job, or parking a flaky machine. Toggle it from the printer card's kebab menu or the Edit dialog.

While in maintenance, the printer:

  • drops out of queue dispatch and the scheduler — no new job is sent to it, and it's skipped by Auto-Queue Routing and model-based assignment;
  • is skipped by auto-drying — the drying scheduler ignores it;
  • is excluded from metrics and sensor-history recording;
  • disconnects from MQTT and stays disconnected until you turn maintenance off (turning it back on reconnects automatically).

The card swaps its connection badge for an amber Maintenance pill () with an Exit button, so it's obvious at a glance which machines are parked.

Toggling on mid-print

Entering maintenance on a printer that's printing or paused asks for confirmation first — the MQTT disconnect stops progress tracking and completion notifications for the in-flight job.

Permission

Maintenance Mode rides on the printer's is_active flag (no separate column), so it needs printers:update — the same permission as editing the printer.

Not the Maintenance Tracker

This is a service state for the whole printer. It's unrelated to the Maintenance tracker, which logs rod / nozzle / belt jobs against usage hours: one parks the machine, the other reminds you when a part is due.

Retiring for good? Archive instead

Maintenance Mode only parks a printer temporarily and keeps its card visible. To retire a printer — sold, decommissioned — Archive it instead: the card is hidden everywhere while its print history is kept.


Bulk Actions

Select multiple printer cards (Select-mode toolbar at the top of the printer page) and apply the same action to all of them at once. Smart-enabled buttons — only active when at least one selected printer is in the right state for that action.

Bulk action Required state Permission
Stop At least one printing or paused printers:control
Pause At least one printing printers:control
Resume At least one paused printers:control
Clear Notifications Always printers:control
Clear Bed At least one in FINISH / FAILED / IDLE with awaiting_plate_clear printers:clear_plate

Selection helpers in the floating toolbar:

  • Select All — every visible card
  • Select by State — pick a state (Printing / Paused / Finished / Idle / Error / Offline) and select all cards in it
  • Select by Location — only visible when at least one printer has a location set

Exit selection mode with Esc or the floating toolbar's X.


Status Badges

Three small icon-only badges sit in the top status row of every card:

Badge Green Red / Yellow Notes
SD Card inserted red when missing All printers
Door closed yellow when open X1 / P1S / P2S / X2D / H2 series only

Door state is decoded from the right MQTT field per printer family (X1: home_flag bit 23; others: stat bit 23) and pushed live over WebSocket — no waiting for the next status poll.


Permission Matrix

Action Permission
Read status, AMS, object list printers:read
Start / pause / resume / stop print printers:control
Bed jog, home, chamber light, print speed, airduct, skip-object, clear-HMS printers:control
Clear plate (acknowledge next job) printers:clear_plate
Bind / unbind a smart plug smart_plugs:update (binding is a field on the plug, set via PATCH /smart-plugs/{id})
Add a printer printers:create
Archive / restore / delete a printer printers:delete
Firmware push firmware:update

  • Monitoring — the live status display these controls sit on top of
  • Print Queue — clear-plate handshake, dispatch flow
  • Smart Plugs — power on/off, auto-power-off thresholds, plug bindings
  • Macros — multi-step custom actions you can fire from the card menu
  • AMS — load / unload / calibrate
  • Notifications — pause / stop / fail event routing

Tips

Confirm before bulk stop

Bulk Stop is irreversible. The toolbar shows a single confirmation for the whole batch — re-read the count before clicking through.

Skip beats stop

If one of eight objects on a plate fell off but the rest are fine, Skip Object keeps the print going. Stop loses everything.

Force MQTT refresh first

When a card looks stuck on a stale value, Force Refresh (pushall) is the cheapest fix. Restart the connection only if pushall doesn't help.

Auto-power-off needs a thermal cool-down

Don't set the cooldown threshold too aggressive — pulling power while the chamber is hot stresses ABS prints and can leave the toolhead warm with no fan running.