The REST API endpoint GET /printers/{id}/status was returning raw
temperatures without filtering based on printer model. WebSocket
broadcasts correctly filtered chamber temp via printer_state_to_dict(),
but the REST endpoint built its own response and bypassed this filter.
When users added a second printer, the frontend would fetch initial
status via REST API, causing chamber temp to reappear on printers
that don't have a chamber sensor (A1, A1Mini, P1P, P1S).
Changes:
- Import supports_chamber_temp in printers.py
- Filter chamber/chamber_target/chamber_heating in get_printer_status()
Fixes#82
The cover and objects endpoints only tried downloading files with the
.gcode.3mf extension pattern, but files uploaded directly (not sliced
via Bambu Studio) are stored as plain .3mf files.
This caused FTP error 550 (file not found) when trying to display cover
images for prints started from BamBuddy archive.
Now tries both naming patterns:
- {name}.gcode.3mf (sliced via Bambu Studio)
- {name}.3mf (uploaded directly)
Fixes#79
- Add light toggle button next to camera button at bottom of card
- Custom ChamberLight SVG icon with on/off states (yellow fill + rays when on)
- Backend endpoint: POST /printers/{id}/chamber-light?on=true|false
- Optimistic UI update for instant feedback
- Works on all Bambu Lab printers (X1, P1, A1, H2D)
- H2D dual chamber lights controlled together
Closes#67
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
- 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
- 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
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".
Root cause: When a print completed with the camera stream popup open,
spawning a second ffmpeg process for finish photo capture caused a
conflict that froze the browser tab and video window.
Solution: Buffer the last frame from active camera streams. When
capturing finish photo, use the buffered frame if a stream is active
instead of spawning a new ffmpeg process.
Backend changes:
- camera.py: Added _last_frames buffer and get_buffered_frame() helper
- main.py: Photo capture uses buffered frame when stream is active
- main.py: Moved slow operations to background tasks (energy calc,
photo capture, smart plug, notifications, maintenance)
- archive.py: Fixed sync file write blocking event loop (asyncio.to_thread)
- printers.py: Added debug endpoint to simulate print completion
Frontend changes:
- useWebSocket.ts: Throttled printer status updates (100ms) to prevent
UI overload from rapid WebSocket messages
- useWebSocket.ts: Debounced archive invalidations (3s) to prevent
cascade of re-renders on print completion
- useWebSocket.test.ts: Updated tests for throttled/debounced handlers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>