When reprinting a multi-plate 3MF file exported with "All sliced file",
the system now asks which plate to print and only maps filaments for
that specific plate.
Backend changes:
- Add GET /archives/{id}/plates endpoint to list available plates
with thumbnails, print times, and per-plate filament requirements
- Add GET /archives/{id}/plate-thumbnail/{index} for plate thumbnails
- Update GET /archives/{id}/filament-requirements to accept plate_id
query parameter for filtering filaments by plate
- Add plate_id field to ReprintRequest schema
- Update POST /archives/{id}/reprint to use plate_id from request body
instead of auto-detecting (maintains backward compatibility)
Frontend changes:
- Add getArchivePlates API method
- Update getArchiveFilamentRequirements to accept optional plateId
- Update reprintArchive to accept plate_id in options
- Add plate selection UI to ReprintModal when multi-plate 3MF detected
- Show plate thumbnails, names, and filament counts in selection grid
- Require plate selection before printing multi-plate files
- Filter filament requirements to show only selected plate's filaments
Tests:
- Add unit tests for multi-plate slice_info.config parsing
- Add unit tests for plate detection from gcode files
- Add integration tests for new plate endpoints
When exporting individual plates from a multi-plate 3MF in Bambu Studio,
all uploaded archives showed plate 1's name and thumbnail regardless of
which plate was actually exported.
Root cause: The 3MF parser used an incorrect XPath lookup (plate_idx
attribute) and didn't extract the plate index from slice_info.config
metadata.
Changes:
- Extract plate index from <metadata key="index" value="N"/> in
slice_info.config
- Remove incorrect plate[@plate_idx='N'] XPath lookup that doesn't
work for single-plate exports
- Set self.plate_number from extracted index so _extract_thumbnail()
uses the correct plate thumbnail (e.g., plate_5.png instead of
plate_1.png)
- Append " - Plate N" to print_name when plate index > 1 to
distinguish multi-plate exports
- Add 7 unit tests for plate index extraction and print_name
enhancement
- Add plug_type field to SmartPlug model ("tasmota" or "homeassistant")
- Add ha_entity_id field for Home Assistant entity reference
- Add global HA settings (ha_url, ha_token, ha_enabled) in Settings
- Create homeassistant_service.py with REST API calls for entity control
- Update smart_plug_manager to dispatch to correct service by plug_type
- Add HA entity discovery endpoint (/ha/entities)
- Add HA connection test endpoint (/ha/test-connection)
- Add Home Assistant tab in AddSmartPlugModal with entity dropdown
- Add HA settings section in Settings → Network tab
- Filter already-configured entities from dropdown
- Update backup/restore to include plug_type and ha_entity_id
- Add frontend tests for HA plug rendering
- Add backend integration tests for HA endpoints
- Update README and CHANGELOG
Closes#91
- Add f3d_path field to PrintArchive model and ArchiveResponse schema
- Add API endpoints for F3D upload/download/delete
- Add cyan badge on archive cards when F3D file is attached
- Add context menu options: Upload/Replace F3D, Download F3D, Remove F3D
- Include F3D files in backup/restore
- Add database migration for f3d_path column
- Add API tests for F3D endpoints
- Rebuild CHANGELOG from GitHub releases
Resolves#90
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
Track individual parts/objects separately from print plates in projects.
Useful for multi-part builds like Voron where 25 plates produce 150 parts.
Backend:
- Add target_parts_count field to Project model
- Calculate parts_progress_percent and remaining_parts in stats
- Auto-detect quantity from 3MF printable objects when archiving
- Sum archive quantities for completed_count (parts)
- Use archive_count for plates progress
Frontend:
- Add "Target Parts" input in project create/edit modal
- Show separate progress bars for plates vs parts
- Stats footer displays both plates and parts count
- Header badge shows parts progress when target set
Scripts:
- Add update_archive_quantities.py to migrate existing archives
Tests:
- Add 5 integration tests for parts tracking
- Add 3 unit tests for 3MF object extraction
Closes#85
The spool detection only checked tray_uuid and tag_uid, but some Bambu Lab
spools have RFID read issues causing these to be missing while still having
valid tray_info_idx (Bambu filament preset ID like "GFA00").
Backend changes (backend/app/services/spoolman.py):
- Add tray_info_idx to AMSTray dataclass
- Parse tray_info_idx from raw MQTT data in parse_ams_tray()
- Check tray_info_idx first in is_bambu_lab_spool() - most reliable indicator
- Bambu Lab presets start with "GF" (GFA00, GFB00, GFL00, etc.)
- Fall back to tray_uuid then tag_uid for unique spool identification
- Add warning when Bambu spool detected but no unique ID for Spoolman
Backend changes (backend/app/api/routes/spoolman.py):
- Update /sync/{printer_id} and /sync-all to pass tray_info_idx
- Guard against empty spool_tag when adding to tracking set
Frontend changes (frontend/src/pages/PrintersPage.tsx):
- Add isBambuLabSpool() helper with same detection logic as backend
- Update all 4 vendor detection locations in AMS cards to use new helper
Detection priority (same on frontend and backend):
1. tray_info_idx starts with "GF" (Bambu preset ID)
2. tray_uuid is valid 32-char hex (non-zero)
3. tag_uid is valid 16-char hex (non-zero)
The spool detection logic only checked tray_uuid (32 hex chars) to identify
Bambu Lab spools. Some spools have RFID read issues causing missing or
invalid tray_uuid while still having valid tag_uid (16 hex chars).
Changes:
- Update is_bambu_lab_spool() to accept tag_uid as fallback parameter
- Prefer tray_uuid for identification, fall back to tag_uid if invalid
- Use whichever valid identifier for Spoolman tag storage and matching
- Update both /sync/{printer_id} and /sync-all endpoints
This fixes spools being incorrectly marked as "Non-Bambu Lab spool (no RFID
tag)" when they have valid tag_uid but missing/zero tray_uuid.
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
New feature: Publish BamBuddy events to external MQTT brokers for integration
with Home Assistant, Node-RED, and other automation platforms.
Backend changes:
- New MQTTRelayService (backend/app/services/mqtt_relay.py) with paho-mqtt
- MQTT settings added to AppSettings schema (enabled, broker, port, auth, TLS)
- New /settings/mqtt/status endpoint for connection status
- Event hooks in main.py, print_queue.py, print_scheduler.py, maintenance.py, smart_plugs.py
- PrinterInfo class and get_printer() method added to PrinterManager
- MQTT reconfiguration added to backup/restore flow
- Printer status throttled to 1 update/sec to avoid flooding
Frontend changes:
- New "Network" tab in Settings (between Filament and API Keys)
- FTP Retry settings moved from General to Network tab
- MQTT configuration card with broker, port, TLS toggle, auth fields
- Port auto-populates when TLS toggled (1883 ↔ 8883)
- Connection status indicator (green/red dot) in tab and card header
- Real-time status polling when on Network tab
Published topics:
- bambuddy/status - Online/offline
- bambuddy/printers/{serial}/status - Printer state (throttled)
- bambuddy/printers/{serial}/print/* - Print lifecycle
- bambuddy/printers/{serial}/ams/changed - AMS changes
- bambuddy/queue/* - Queue events
- bambuddy/maintenance/* - Maintenance alerts
- bambuddy/smart_plugs/* - Plug state/energy
- bambuddy/archive/* - Archive events
Tests:
- Added MQTT settings and status endpoint tests
Closes#78
Fix Applied:
1. Added supports_chamber_temp() helper function that returns True only for X1/X1C/X1E, P2S, and H2 series
2. Modified printer_state_to_dict() to filter out chamber, chamber_target, chamber_heating from temperatures for unsupported models
3. Added model caching in PrinterManager so we can look up the model without a database query
4. Updated all callers (main.py, websocket.py) to pass the model
The chamber temperature widget will now simply not appear for P1S/P1P/A1/A1Mini printers since the temperatures.chamber field won't be sent to the frontend.
- Moved BAMBU_HEX_COLORS mapping and getColorName()/hexToColorName() functions to a shared location
- Exported functions for use across components
- Updated modals to use shared colors:
- ReprintModal.tsx - removed ~100 lines of duplicate color code, now imports from utils/colors
- AddToQueueModal.tsx - same cleanup
- EditQueueItemModal.tsx - same cleanup
- Added AMS mapping to EditQueueItemModal:
- Added state for showFilamentMapping, isRefreshing, manualMappings
- Added queries for filament requirements and printer status
- Added loadedFilaments, filamentComparison, amsMapping memos
- Added collapsible filament mapping UI section (same as other modals)
- Initializes manualMappings from existing item.ams_mapping
- Submits ams_mapping when saving changes
- Backend changes:
- Added ams_mapping field to PrintQueueItemUpdate schema
- Updated update_queue_item route to serialize ams_mapping to JSON
- Frontend API client:
- Added ams_mapping to PrintQueueItemUpdate interface
- Changed "Print" to "Reprint" on archive card button (ArchivesPage.tsx:690)
- Bumped service worker to v22
- Comprehensive hex-based color mapping (~200 Bambu colors from CSV)
- Fixed tooltips to use Bambu color lookup
- Widened modals (max-w-md → max-w-lg)
- Adjusted grid layout to fit long color names
- Service worker bumped to v21
Pending changes in bambuddy repo:
- CHANGELOG.md, README.md
- backend/app/api/routes/print_queue.py
- backend/tests/integration/test_print_queue_api.py
- frontend components (ReprintModal, AddToQueueModal, EditQueueItemModal)
- sw.js (v21)
- ReprintModal: Dropdown to override auto-matched AMS slots
- AddToQueueModal: Collapsible filament mapping section
- Backend: Store ams_mapping in print queue, apply when print starts
- Color names in dropdowns (decoded from Bambu codes or derived from hex)
- Blue ring indicator for manually selected vs auto-matched slots
- Status indicators: green (match), yellow (type only), orange (not found)
Closes#76
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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
Resolves FTP transfer failures on A1/A1 Mini printers caused by SSL
session reuse incompatibility. Also adds configurable FTP timeout
setting for slow WiFi connections.
Changes:
- Add SSL session reuse bypass for A1/A1 Mini printers (auto-detected)
- Add printer_model parameter to FTP functions for model detection
- Add configurable FTP timeout (10-120s, default 30s) in Settings
- Update all FTP callers: archiving, reprint, timelapse, firmware upload
Technical details:
- A1/A1 Mini printers don't support vsFTPd's SSL session reuse
- X1C/P1S continue to use session reuse as required by their FTP server
- ImplicitFTP_TLS now accepts skip_session_reuse flag
- BambuFTPClient auto-detects A1/A1 Mini and sets flag accordingly
Added:
- Archive list view: edit/delete buttons and context menu with full feature parity
- Archive object count display on cards (extracted from 3MF metadata)
- Cross-view archive highlighting: click in calendar/project to highlight in card view
- Context menu button (⋮) on cards and list rows for easy access
- Spoolman: clear location when spools are removed from AMS
Fixed:
- QR code endpoint 500 error (added qrcode[pil] dependency)
Previously, when syncing to Spoolman, the location field was set to the
printer/AMS slot but was never cleared when the spool was removed from
the AMS.
Now during sync, the system tracks which tray UUIDs are currently in the
AMS and clears the location for any spools that were previously at this
printer but are no longer present.
Changes:
- Add clear_location parameter to update_spool() method
- Add find_spools_by_location_prefix() to find spools at a printer
- Add clear_location_for_removed_spools() to clear stale locations
- Update sync_printer_ams and sync_all_printers endpoints to clear
locations for removed spools after syncing
Features:
- Add print options UI to reprint modal (bed leveling, flow calibration,
vibration calibration, first layer inspection, timelapse)
- Collapsible "Print Options" section with toggle switches
- Default values: bed leveling=on, vibration_cali=on, others=off
Fixes:
- Fix AMS mapping format to match Bambu Studio exactly
- Use slot_id from 3MF to position tray IDs correctly
- Fill unused slots with -1 placeholder
- Add ams_mapping2 with detailed {ams_id, slot_id} pairs
- Fix print command format for proper printer recognition
- Add auto_bed_leveling, cfg, extrude_cali_flag, nozzle_offset_cali
- Use American spelling "bed_leveling" (not British "bed_levelling")
- Match sequence_id format from official apps
- Prevent duplicate tray assignment in filament matching
This resolves the "stuck at filament change" issue on multi-color reprints
affecting X1C and other multi-AMS printer configurations.
Features:
- Add wiki_url field to MaintenanceType for custom type documentation links
- Add printer_model to MaintenanceStatus for model-specific URL mapping
- Display external link icon next to maintenance item names
- Map system maintenance types to Bambu Lab wiki pages by printer model:
- Lubricate Linear Rails, Clean Nozzle/Hotend, Check Belt Tension
- Clean Carbon Rods (X1/P1 only), Clean Build Plate, Check PTFE Tube
- HEPA/Carbon Filter, Left Nozzle Rail (H2 series)
- Add Documentation Link input to custom type create/edit forms
Bug fix:
- Fix 500 error when assigning maintenance type to printer (lazy loading)
Database:
- Add migration for wiki_url column on maintenance_types table
- Add /api/v1/support/debug-logging endpoints to toggle debug log level
- Add /api/v1/support/bundle endpoint to generate ZIP with system info and logs
- Debug logging state persists across restarts via Settings database
- Add debug logging indicator banner in Layout with real-time duration timer
- Add Support & Troubleshooting section to System Information page
- Privacy protection:
- Filter sensitive settings (emails, keys, tokens, URLs, configs)
- Sanitize paths to remove usernames
- Remove hostname from collected data
- Replace IP addresses with [IP] and emails with [EMAIL] in logs
- Add privacy info panel explaining what data is/isn't collected
- Require debug logging to be enabled before downloading support bundle
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
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
- 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
- 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.