Enables checking and uploading firmware updates for printers operating
in LAN-only mode without Bambu Cloud connectivity.
Features:
- Automatic firmware version checking against Bambu Lab servers
- Orange "Update" badge on printer cards when updates available
- Firmware update modal with version info and release notes
- One-click firmware upload to printer SD card via FTP
- Real-time upload progress (actual bytes transferred)
- Step-by-step instructions for triggering update from printer
- Local firmware caching for faster re-uploads
- Supports all Bambu Lab printer models
New files:
- backend/app/services/firmware_check.py - Version checking service
- backend/app/services/firmware_update.py - Upload orchestration
- backend/app/api/routes/firmware.py - REST API endpoints
Also includes:
- FTP upload progress callback support
- 10-minute upload timeout protection
- Firmware cache directory in .gitignore
- Correct SSDP model codes: C11=P1P, C12=P1S, N7=P2S, C13=X1E
- Fix serial prefixes based on actual Bambu serial format
- Add confirmation modal for pending upload discard
- Sort model dropdown alphabetically, remove internal codes
- Add "Setup Required" warning with link to wiki documentation
- Update wiki with certificate installation and platform setup guides
Features:
- Configurable printer model for virtual printer emulation
- Supports X1 series (X1C, X1, X1E), P series (P1S, P1P, P2S),
A1 series (A1, A1 Mini), and H2 series (H2D, H2C, H2S)
- Dropdown in Settings > Virtual Printer to select model
- Model affects SSDP discovery and slicer compatibility
- Model change restarts virtual printer services automatically
Backend:
- Added VIRTUAL_PRINTER_MODELS mapping in manager.py
- Added virtual_printer_model setting in database
- New GET /api/v1/settings/virtual-printer/models endpoint
- Updated PUT /api/v1/settings/virtual-printer to accept model
Frontend:
- Added model dropdown to VirtualPrinterSettings component
- Status display shows selected model name
- Model change disabled while virtual printer is running
Tests:
- Added 3 unit tests for model configuration
- Updated frontend test mocks for getModels API
Features:
- Resizable printer cards (S/M/L/XL) with toolbar controls on Printers page
- Queue Only mode for staging prints without automatic scheduling
- "Queue Only" option in add/edit queue modals
- Purple "Staged" badge and Play button to release to queue
- manual_start field in database with migration
Fixes:
- Improved camera stream stuck detection with automatic reconnection
Tests:
- Added 16 integration tests for print queue API endpoints
- Controls section: New section before Filaments with fan status and printer controls
- Part cooling fan (Fan icon, cyan)
- Auxiliary fan (Wind icon, blue)
- Chamber fan (AirVent icon, green)
- Stop/Pause/Resume buttons moved from Temperature section
- Real-time updates: Fan speeds now broadcast via WebSocket
- Backend: Parse MQTT fan data (cooling_fan_speed, big_fan1_speed, big_fan2_speed)
- Convert 0-15 scale to 0-100%
- Always-visible badges with dynamic coloring based on fan state
- Removed horizontal dividers before Controls and Filaments sections
- New APIBrowser component with full OpenAPI schema integration
- Fetches and parses /openapi.json automatically
- Groups endpoints by API tags (printers, archives, settings, etc.)
- Expandable endpoint sections with color-coded method badges
- Path parameter, query parameter, and JSON body editors
- Auto-populates request body with schema examples
- Live API request execution with response display
- Response shows status code, timing, and formatted JSON
- Copy response button with clipboard fallback
- Search to filter endpoints across all categories
- Expand All / Collapse All buttons
- Link to Swagger UI (/docs)
- Two-column layout for API Keys tab
- Left: API key management + webhook documentation
- Right: API Browser with dedicated test key input
- Parameter validation
- Shows warning for missing required parameters
- Validates before sending requests to avoid 422 errors
- UX improvements
- "Use in API Browser" button on newly created keys
- Responsive layout (stacked on mobile, side-by-side on xl+)
- Track number of items per print job (default: 1)
- Project stats now show total items vs print jobs
- Progress bar counts items toward target, not just archives
- "Items Printed" field in archive edit modal
Backend:
- Added quantity field to PrintArchive model
- Database migration for quantity column
- Updated project stats to use SUM(quantity)
- Updated backup/restore to include quantity
- Updated CSV/Excel export with quantity field
Frontend:
- Added quantity input to EditArchiveModal
- Updated ProjectsPage to display total_items
- Updated ProjectDetailPage stats
- Fixed project delete not refreshing the list
- Link to Spoolman: Manually link existing Spoolman spools to AMS trays
- Hover over AMS slot to see "Link to Spoolman" button
- Select from list of unlinked Spoolman spools
- Automatically sets extra.tag field in Spoolman
- Spool UUID display: View and copy Bambu Lab spool UUID in AMS hover card
- Shows first 8 chars with copy button (full UUID to clipboard)
- Fallback copy method for HTTP contexts
- Sync feedback: Shows synced count and skipped spools with reasons
- Expandable list when more than 5 skipped
- Color swatches for identification
- Fixed Spoolman 400 Bad Request: extra field values must be valid JSON
- Updated documentation (wiki, website)
- Skip Objects Modal:
- Object ID markers overlaid on preview image (grid layout)
- Large prominent ID badges to match printer display
- Info banner explaining to match IDs with printer screen
- Layer warning when skip unavailable (layer <= 1)
- Red badge on button showing skipped count
- Preview image now shown when paused (not just running)
- Close with ESC key or click outside modal
- Full light/dark theme support
- Backend:
- Extract object positions from 3MF (include_positions=True)
- API returns x/y coordinates for objects (when available)
- Parse s_obj from printer MQTT for skipped state persistence
- Cover URL available in PAUSE/PAUSED states
- Tests:
- Added test for objects with position data
- Auto-resize to fit video resolution on first open
- Persist window size and position to localStorage
- Restore saved window state for subsequent opens
- Add utils/slicer.ts with OS detection for protocol handler
- Windows: bambustudio://, macOS/Linux: bambustudioopen://
- Update all usages in ArchivesPage.tsx and ModelViewerModal.tsx
Implement comprehensive theme customization with independent settings for
dark and light modes:
- Style layer: Classic (clean shadows), Glow (accent-colored glow effects),
Vibrant (dramatic deep shadows)
- Background layer: Neutral, Warm, Cool (light mode); plus OLED, Slate,
Forest (dark mode only)
- Accent colors: Green, Teal, Blue, Orange, Purple, Red
All combinations work independently (e.g., Glow + Forest + Teal). Settings
sync across devices via database and show toast confirmations on change.
Backend:
- Add 6 new settings fields (dark_style, dark_background, dark_accent,
light_style, light_background, light_accent)
- Add integration test for theme settings API
Frontend:
- Refactor index.css with 3-layer CSS variable system
- Update ThemeContext for dual-mode theme management
- Add Appearance section to Settings page with 6 dropdowns
- Update components for new ThemeContext API
- Virtual printer appears in Bambu Studio/Orca Slicer via SSDP discovery
- Secure TLS/MQTT communication with auto-generated certificates
- Queue mode (pending uploads) or auto-start mode
- Configurable access code for authentication
- Docker support with network_mode: host and certificate persistence
- Fix backup/restore for virtual printer settings (auto-save no longer overwrites)
- Add fuzzy color matching for filament comparison
Colors within RGB threshold of 40 are considered a match, fixing
cases where 3MF and printer report slightly different hex values
for the same filament color (e.g., beige #F5F5DC vs #FCECD6)
- Add POST /printers/{id}/refresh-status endpoint
Sends MQTT pushall command to request fresh AMS data from printer
- Improve Re-read button in filament check section
- Now triggers backend refresh before refetching status
- More prominent styling with text label and border
- 500ms delay after pushall to allow printer to respond
- Add AMS slot labels to matched filament display
Shows location like "PLA (AMS-B Slot 3)" instead of just "PLA"
- Add color hex tooltips on filament color circles
- Features:
- Tasmota device discovery: Auto-detect network and scan for Tasmota devices
in Add Smart Plug modal. Supports devices with/without authentication.
- Switchbar: Quick access widget in sidebar footer for controlling smart plugs
from anywhere in the app. Shows real-time status and power consumption.
- AMS Filament Preview:
- Add GET /archives/{id}/filament-requirements endpoint to extract
filament data from archived 3MF slice_info.config
- Show filament comparison in reprint modal when printer is selected
- Compare both filament type AND color with visual indicators:
- Green checkmark: Type and color match
- Yellow warning: Same type, different color
- Orange warning: Different type or empty slot
- Handle AMS-HT units (id >= 128) and virtual tray (slot 254)
- Normalize color formats between API (RRGGBBAA) and 3MF (#RRGGBB)
- File Type Badge:
- Archive cards show GCODE (green) or SOURCE (orange) badge
- Helps users identify which files have print data vs source-only
- Badge appears next to printer name in card content area
- Camera Stream Stability:
- Increase ffmpeg read timeout from 10s to 30s
- Add ffmpeg RTSP options: -timeout, -buffer_size, -max_delay
- Add frontend auto-reconnection with exponential backoff (2s-30s)
- Show reconnection UI with countdown and attempt counter
- Add TimelapseEditorModal component with visual timeline scrubber
- Add timelapse processing endpoints (info, thumbnails, process)
- Add TimelapseProcessor service using FFmpeg for video processing
- Support trim (start/end), speed (0.25x-4x), and audio overlay
- Add Edit button to TimelapseViewer
- Fix browser caching with timestamp query parameter
- Change default timelapse playback speed from 2x to 1x
- Detect Docker environment automatically via /.dockerenv and cgroup
- Show subnet input field in Add Printer dialog when running in Docker
- Scan IP range for Bambu printer ports (8883 MQTT, 990 FTPS)
- Query SSDP to get printer name/serial/model from discovered IPs
- Map raw SSDP model codes to friendly names (BL-P001→X1C, O1D→H2D)
1. "Unknown Status (255)" bug
File: backend/app/services/printer_manager.py:291-293
Problem: A1/P1 printers send stg_cur=255 when idle (unlike X1 which uses -1). The code treated 255 as a valid stage number and returned "Unknown stage (255)".
Fix: Changed the condition from if state.stg_cur >= 0: to if 0 <= state.stg_cur < 255: so that 255 is now treated as "no calibration stage" (same as -1).
2. AMS humidity/temp displaced on mobile
File: frontend/src/pages/PrintersPage.tsx:1164-1212
Problem: The AMS row used a rigid horizontal flex layout that didn't adapt to narrow mobile screens, causing humidity/temperature indicators to be displaced.
Fix:
- Added flex-wrap to allow wrapping on very narrow screens
- Added ml-auto to humidity/temp section to keep it right-aligned
- Added max-w-[60px] sm:max-w-none to truncate long filament names on mobile
- Changed gap from fixed gap-3 to responsive gap-2 sm:gap-3
Tests Added
4 new unit tests for get_derived_status_name:
- test_stg_cur_255_returns_none - Verifies A1/P1 idle state
- test_stg_cur_negative_one_returns_none_when_idle - Verifies X1 idle state
- test_valid_stage_returns_name - Verifies valid stages work
- test_stg_cur_zero_returns_printing - Verifies printing state
All 382 tests pass.
prints (not just completed), matching get_printer_total_hours behavior
- Add option to keep or delete archives when deleting a printer
- Custom maintenance types no longer auto-assign to all printers
- Add UI to manually assign/remove custom maintenance types per printer
- Add backend endpoints for assigning types to printers and removing items
- Exclude static/assets from large file pre-commit check
- Add getStatusDisplay() helper in frontend to format status nicely
- Add get_derived_status_name() in backend to compute status from:
- stg_cur calibration stages (bed leveling, vibration comp, etc.)
- Temperature data when stg_cur unavailable (heating heatbed/nozzle)
- Include stg_cur and stg_cur_name in WebSocket broadcasts
- Update broadcast status key to detect heating phase changes
Printer cards now show: "Heating heatbed", "Heating nozzle", "Preparing",
"Auto bed leveling", "Cleaning nozzle tip", and 60+ other stage names
instead of just "Printing" or "Idle".
When navigating to the printer page after a print completed, status
metrics would animate slowly from mid-print values to final state.
Root cause: The message queue processed messages one at a time with 16ms
delays. If 50+ status updates queued during a print, they took 800ms+ to
process, causing multiple throttle windows and the visual "timelapse".
Solution: Handle printer_status messages directly without queueing.
They're already throttled (100ms) so don't need queue rate limiting.
Other message types still use the queue.