Enhance Home Assistant script support with automation triggers and
printer card visibility control.
- Script automation: Run scripts automatically when main plug turns on/off
- Show/hide scripts on printer cards (configurable per script)
- Scripts appear in dedicated row on printer cards with quick-run buttons
- Toast notification when triggering scripts from settings/sidebar
Closes#176
- Add trimesh and matplotlib dependencies for software-based 3D rendering
- Create stl_thumbnail service with generate_stl_thumbnail() function
- Handle mesh simplification for large files (>100k vertices)
- Auto-generate thumbnails during STL file upload and ZIP extraction
- Add POST /library/files/{id}/regenerate-thumbnail endpoint
- Add POST /library/generate-stl-thumbnails batch endpoint
- Add "Generate Thumbnails" button to file manager toolbar
- Add "Regenerate Thumbnail" option to file context menu
- Add unit and integration tests for new functionality
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove created_at from backup_metadata.json
- Remove exported_at from K-profile files
- Remove exported_at from cloud profile files (filament, printer, process)
- Remove exported_at from app settings backup
- Git already tracks file modification history, so these were redundant
- Backups now only show changes in git diff when actual data changes
Add new setting "Check printer firmware" in Settings → General → Updates
that allows users to disable automatic firmware update checks from
Bambu Lab servers.
Closes#169
Some A1/A1 Mini firmware versions incorrectly report stg_cur=0 (which
maps to "Printing") even when the printer is idle. This is a known
firmware bug also observed in the Home Assistant Bambu Lab integration.
- Add A1_MODELS constant listing affected model variants
- Add has_stg_cur_idle_bug() helper to identify affected models
- Update get_derived_status_name() to check gcode_state before stg_cur
for A1 models: if IDLE + stg_cur=0, return None to show "Idle"
- Fix only applies when all conditions match (A1 model + IDLE + stg_cur=0)
- Non-A1 printers and A1 printers without the bug are unaffected
Closes#168
Printers report filament_id (e.g., GFA00) but the Bambu Cloud API expects
setting_id format which has an "S" inserted after "GF" (e.g., GFSA00).
- Add _filament_id_to_setting_id() helper function
- Transform IDs before API calls: GFx## -> GFSx##
- User presets (P-prefix) and already-correct IDs unchanged
- Improved warning message to show both original and transformed IDs
Expose printer telemetry at /api/v1/metrics in Prometheus text format for
integration with Grafana, Prometheus, and other monitoring systems.
Backend:
- Add metrics.py route with GET /api/v1/metrics endpoint
- Support optional bearer token authentication
- Export printer metrics: connection, state, temperatures, fans, WiFi
- Export print metrics: progress, remaining time, layer count
- Export statistics: prints by status, filament used, print time
- Export queue metrics: pending and active jobs
- Add prometheus_enabled and prometheus_token settings
Frontend:
- Add Prometheus Metrics card in Settings → Network tab
- Toggle to enable/disable metrics endpoint
- Optional bearer token field for authentication
- Display list of available metrics
Tests:
- Add test_metrics_api.py with 7 integration tests
- Test access control (disabled, enabled, token auth)
- Test metrics format and content validation
- Automatically turn on chamber light before plate check if it's off
- Restore light to original state after modal closes or check completes
- Add 2.5s delay for light to turn on and camera to adjust exposure
- Remove manual light warning from plate check modal
- Apply to both manual plate checks (modal) and automatic checks on print start
The print queue now supports two sources:
- archive_id: Print from existing archive (existing behavior)
- library_file_id: Print from file manager library files (NEW)
Previously, queue items from the file manager failed with "Archive not
found" because the scheduler only handled archive-based prints.
Changes:
- Add LibraryFile model import
- Update _start_print() to handle both archive and library file sources
- Handle absolute vs relative file paths correctly
- Update logging and MQTT notifications to use correct filename
Fixes GitHub issue #163
The scheduler compared timezone-aware datetime.now(UTC) with naive
datetimes from the SQLite database, causing "can't compare offset-naive
and offset-aware datetimes" error.
Fixed by adding UTC timezone to naive datetimes before comparison.
The print scheduler only considered IDLE, FINISH, and unknown as valid
idle states. This caused the queue to not process items when the printer
was in FAILED state (e.g., after an aborted print).
Added FAILED to the list of idle states since a failed print means the
printer is ready to accept a new print job.
New feature to automatically backup K-profiles, cloud profiles, and app
settings to a GitHub repository with scheduled or on-demand execution.
Features:
- Configure GitHub repo URL and Personal Access Token
- Schedule backups hourly, daily, or weekly (background scheduler)
- Manual backup trigger with real-time progress tracking
- Skip unchanged commits (only creates commit when data changes)
- Backup history log with status and commit links
- Requires Bambu Cloud login for full profile access
- New Settings → Backup & Restore tab consolidating all backup options
- GitHub backup config included in local backup/restore (except PAT)
Backend:
- New models: GitHubBackupConfig, GitHubBackupLog
- New service: GitHubBackupService with scheduler and GitHub API client
- New routes: /github-backup/* for config, status, logs, and triggers
- Updated settings.py to include github_backup in backup/restore
Frontend:
- New GitHubBackupSettings.tsx component with auto-save
- Updated SettingsPage with Backup tab and status indicator
- Added API types and methods to client.ts
Tests:
- Backend integration tests for all GitHub backup API endpoints
- Frontend API type and endpoint tests
- Add "Plate Detection" option to backup modal
- Store printer_id_to_serial mapping in backup for calibration files
- Remap printer IDs during restore based on serial numbers so files
like printer_3_ref_0.jpg get correctly renamed if printer 3 becomes
printer 2 on the new system
- Add parents=True to mkdir calls in config.py to fix startup crash
- Labels/metadata are now correctly restored via the metadata.json files
- Check cv2.imwrite() return value to catch silent failures
- Verify reference image file exists after save
- Validate file size is reasonable (>1KB) to detect corruption
- Add logging for save, rotate, and delete operations
- Use temp directory for plate calibration during tests to avoid
deleting real user calibration files
Previously, calibration could report success even if the image file
failed to save. Additionally, running tests would delete real
calibration files because tests shared the same plate_calibration_dir.
New Features:
- Queue bulk edit: Select multiple pending items and edit printer
assignment, print options, or cancel them at once (Issue #159)
- Tri-state toggles (unchanged/on/off) for selective field updates
Fixes:
- Progress milestone notifications showed wrong time (e.g., "17m" instead
of "17h 47m") - fixed by converting remaining_time from minutes to
seconds (Issue #157)
- File Manager folder names now show full name on hover tooltip (Issue #160)
Backend:
- Added PATCH /queue/bulk endpoint for bulk updates
- Route ordering fixed to prevent /bulk matching as /{item_id}
Frontend:
- Added checkbox selection to pending queue items
- Added bulk action toolbar with Select All, Edit Selected, Cancel Selected
- Created BulkEditModal with tri-state toggles for each setting
Tests:
- Added 7 integration tests for bulk update endpoint
Closes#159
The remaining_time from printer state is in minutes (from mc_remaining_time),
but _format_duration() expects seconds. This caused "17h 47m" to display as
"17m" in milestone notifications.
Closes#157
- Add USB camera type to external camera service
- Auto-detect available V4L2 devices on Linux
- New API endpoint: GET /api/v1/printers/usb-cameras
- Use ffmpeg for USB camera capture and streaming
- Add "USB Camera (V4L2)" option in Settings UI
- Debounce camera URL input to avoid saving on every keystroke
Closes#143
Automatically detect if objects are on the build plate before printing
and pause the print immediately if detected.
Features:
- Per-printer toggle to enable/disable plate detection
- Multi-reference calibration: store up to 5 reference images per printer
for different plate types (textured, smooth, high-temp, etc.)
- Automatic print pause when objects detected at print start
- Push notification and WebSocket alert when print is paused
- ROI (Region of Interest) calibration UI with sliders to adjust
detection area
- Reference management: view thumbnails, add labels, delete references
- Works with both built-in and external cameras
- Uses buffered camera frames when stream is active (no blocking)
- Split button UI: main button opens modal, chevron toggles on/off
- Green visual indicator when plate detection is enabled
- Included in backup/restore
The on_print_progress notification method existed but was never called.
Added milestone tracking in on_printer_status_change that:
- Tracks last notified milestone per printer
- Detects when progress crosses 25%, 50%, 75% thresholds
- Sends notification via notification_service.on_print_progress()
- Resets tracking when progress drops below 5% (new print)
Closes#157
Printers without an SD card store files in the root folder `/` instead of
`/cache`. Added root folder to search paths in both main.py and bambu_ftp.py
so 3MF files can be found regardless of storage configuration.
Closes#146
Features:
- Export single project as ZIP containing project.json and all files
from linked library folders
- Export all projects as JSON (metadata only) for bulk backup
- Import from ZIP (creates folders and extracts files) or JSON
- New /api/v1/projects/import/file endpoint for file uploads
- Frontend buttons on Projects page and Project Detail page
- BOM items are now fully editable (not just checkbox toggle)
When spools were removed from AMS slots, Bambuddy continued showing them
as loaded. Fixed for both old and new AMS models:
- Old AMS: Allow empty values to overwrite slot data during merge
(tray_type, tray_color, tag_uid, etc. were being skipped)
- New AMS (AMS 2 Pro): Parse tray_exist_bits bitmask to detect empty
slots and clear their data accordingly
Added 3 unit tests for AMS data merging behavior.
Closes#147
Allow users to manually set external URLs for archives from Printables,
Thingiverse, or other sources. The Globe button now opens the external
link when set, falling back to auto-detected MakerWorld URL.
- Add external_url field to PrintArchive model with migration
- Add input field to archive edit modal
- Update Globe button: external_url > makerworld_url > disabled
- Include external_url in backup/restore
- Add API test for external_url update
- Update docs (changelog, wiki, website)
Closes#151
Add support for external network cameras (MJPEG, RTSP, HTTP snapshot)
that replace a printer's built-in camera when configured.
Features:
- Live streaming on printers page (replaces built-in camera)
- Finish photo capture from external camera on print complete
- Layer-based timelapse: captures frame on each layer change,
stitches to MP4 video on print completion
Backend changes:
- Add external_camera_url, external_camera_type, external_camera_enabled
fields to Printer model with database migration
- New external_camera.py service: MJPEG/RTSP/snapshot frame capture,
connection testing, MJPEG stream generation
- New layer_timelapse.py service: TimelapseSession management,
layer-by-layer frame capture, ffmpeg video stitching
- Add on_layer_change callback to MQTT client and printer manager
- Update camera routes with external camera streaming and tracking
- Update print lifecycle hooks for timelapse start/stitch/cancel
- Add external camera fields to backup/restore
- Rate limiting for external camera streams (prevents browser freeze)
Frontend changes:
- Add external camera configuration UI in Settings > Camera
- Per-printer enable toggle, URL input, type selector, test button
- Toast notification on save
Closes#143
- Add checkbox selection for individual files
- Add Select All / Deselect All buttons
- Download single file directly, multiple files as ZIP archive
- Add POST /printers/{id}/files/download-zip endpoint
- Clear selection after successful download
- Support bulk delete for multiple files
- Update docs (changelog, wiki, website)
Closes#144
File Manager improvements (#121):
- New option to create folder from ZIP filename (e.g., MyProject.zip → MyProject/)
- Upload modal now accepts all file types, not just ZIP files
- Updated drop zone text to clarify all files are supported
- Both options can be combined: create folder + preserve internal structure
Camera zoom/pan improvements (#132):
- Pan range now based on actual container size instead of fixed pixels
- Users can pan across the entire zoomed image at any zoom level
- Added pinch-to-zoom gesture for mobile (two fingers)
- Added single finger pan when zoomed in on touch devices
- Pan while pinching to reposition zoom focus
- Both EmbeddedCameraViewer and standalone CameraPage updated
Home Assistant integrations may report units in different cases (e.g., "w"
instead of "W", "kwh" instead of "kWh"). The sensor entity filter was using
case-sensitive comparison, causing valid energy sensors to not appear in
the Energy Monitoring dropdown.
Changed unit comparison to case-insensitive matching in list_sensor_entities().
Closes#119
P2S printer creates fallback archives without thumbnails/metadata because
FTP couldn't find 3MF files. The P2S uses different directory structure
(/data/Metadata/) and doesn't have a /cache directory.
Changes:
- Add P2S to SKIP_SESSION_REUSE_MODELS for SSL compatibility
- Add /data/ and /data/Metadata/ to 3MF download paths
- Update fallback search to try multiple directories instead of just /cache
- Add /data paths to FTP storage scan directories
Closes#146
- Add "Recalculate Costs" button to Dashboard that updates all archive
costs using current filament prices (Issue #120)
- Track reprints and add cost to existing archive total on completion,
so statistics accurately reflect total filament expenditure
Closes#120