- Add new `printers:ams_rfid` permission for re-reading AMS RFID tags
- Allows granting RFID re-read access without full printer control
- Operators group includes this permission by default
- Previously used `printers:control` which grants broader access
- Permission available in Settings > Users > Group Editor
Closes#204
Backend:
- Split update/delete permissions into *_own and *_all variants:
- queue:update_own/all, queue:delete_own/all
- archives:update_own/all, archives:delete_own/all, archives:reprint_own/all
- library:update_own/all, library:delete_own/all
- Add require_ownership_permission dependency factory in auth.py
- Enforce ownership checks on all relevant API endpoints:
- archives.py: PATCH, DELETE, POST /reprint
- print_queue.py: PATCH, DELETE, POST /cancel, PATCH /bulk
- library.py: PUT /files, DELETE /files, POST /bulk-delete, DELETE /folders
- Add user items count endpoint: GET /users/{id}/items-count
- Add delete_items parameter to DELETE /users/{id}
- Explicitly set created_by_id to NULL on user deletion for DB portability
- Add permission migration for existing groups in database.py
- Add require_permission_if_auth_enabled for folder delete
Frontend:
- Add canModify helper to AuthContext for ownership-based checks
- Update ArchivesPage: use canModify for edit/delete/reprint buttons
- Update QueuePage: use canModify for edit/delete/cancel buttons
- Update FileManagerPage: use canModify for edit/delete buttons
- Update SettingsPage: add user deletion modal with item handling options
- Update StatsPage: use archives:update_all for recalculate costs
- Update Permission type with new ownership permissions
- Add getUserItemsCount and update deleteUser API methods
Tests:
- Add test_ownership_permissions.py with 28 comprehensive tests
- Test admin *_all permissions, operator *_own permissions
- Test bulk operations skip non-owned items
- Test auth disabled allows all operations
- Test user deletion with/without items
Closes#205
Track and display who performs key actions in Bambuddy:
- Archives: who uploaded each archive file
- Library: who uploaded each file in File Manager
- Queue: who added each print job to the queue
- Printers: who started the current print (reprint tracking)
Backend changes:
- Add created_by_id column to print_archives, library_files, print_queue tables
- Add database migrations for new columns (auto-run on startup)
- Update archive, library, and queue routes to capture current user
- Add current-print-user endpoint for printer reprint tracking
- Track reprint user in PrinterManager in-memory state
- Fix file uploads not sending auth headers (FormData requires explicit headers)
Frontend changes:
- Display username on archive cards, library files, queue items
- Show "Started by" on printer cards during active prints
- Add auth headers to all 12 FormData upload functions
- Update TypeScript types for user tracking fields
Tests:
- Add unit tests for PrinterManager user tracking methods (7 tests)
- Add integration tests for current-print-user endpoint (3 tests)
- Add integration tests for library file user tracking (3 tests)
Works when authentication is enabled; gracefully hidden when disabled.
Closes#206
Library files now store paths relative to base_dir instead of absolute
paths. This ensures thumbnails and files work correctly after restoring
a backup on a different system or with a different data directory.
Changes:
- Add to_relative_path() and to_absolute_path() helper functions
- Update file upload, ZIP extraction, and STL thumbnail generation
to store relative paths
- Update download, thumbnail, gcode, and delete endpoints to resolve
relative paths when accessing files
- Add database migration to convert existing absolute paths to relative
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The code is ready for testing. After pushing to the remote host:
1. The migration will run automatically on startup, converting any existing absolute paths
2. New files will be stored with relative paths
3. Thumbnails should display correctly after backup/restore
Replace the complex JSON-based backup system (~2000 lines) with a simple
approach that copies the SQLite database and all data directories into a
single ZIP file.
Backend changes:
- Add close_all_connections() and reinitialize_database() helpers to database.py
- New GET /backup endpoint: creates complete ZIP with bambuddy.db and all
data directories (archive, virtual_printer, plate_calibration, icons, projects)
- New POST /restore endpoint: extracts ZIP, replaces database and directories,
requires restart after restore
- Move legacy endpoints to /backup-legacy and /restore-legacy for transition
Frontend changes:
- Simplify api.exportBackup() - no longer takes category parameters
- Simplify api.importBackup() - no longer takes overwrite parameter
- Remove BackupModal and RestoreModal components from GitHubBackupSettings
- Add simple Download/Restore buttons with inline logic
- Add blocking modal overlay during backup/restore operations
- Add beforeunload handler to prevent accidental navigation
- Show operation status messages during backup/restore
Benefits:
- ~100 lines vs ~2000 lines of backup/restore code
- Complete by definition - SQLite database contains ALL data
- No code changes needed when schema changes
- No ID remapping required - IDs stay the same
- Faster - file copy vs querying all tables
Resolved conflicts:
- CHANGELOG.md: Kept both HA Script Support and STL Thumbnail features
- database.py: Kept both migration sets (UNIQUE constraint removal + queue columns)
- SmartPlugCard.tsx: Merged script UI support with base styling
- static/: Rebuilt frontend with merged changes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement a full permissions system replacing simple admin/user roles:
Backend:
- Add Group model with many-to-many user relationship
- Add 50+ granular permissions (resource:action pattern)
- Create default groups: Administrators, Operators, Viewers
- Add permission-checking dependencies for route protection
- Add groups API endpoints (CRUD, user assignment)
- Add change password endpoint for users
- Update backup/restore to include groups
- Migrate existing users to groups on startup
Frontend:
- Add GroupsPage for managing groups and permissions
- Add permission helpers to AuthContext (hasPermission, hasAnyPermission)
- Add PermissionRoute component for protected routes
- Disable buttons/features based on permissions (with tooltips)
- Add change password modal in sidebar for all users
- Add forgot password info modal on login page
- Show user groups in UsersPage with group assignment
Testing:
- Add integration tests for groups API
- Add tests for user-group assignments
- Add tests for change password endpoint
- Seed default groups in test fixtures
Closes#28#161
Implement centralized tag management for print archives:
- GET /archives/tags endpoint to list all tags with usage counts
- PUT /archives/tags/{name} endpoint to rename tags across archives
- DELETE /archives/tags/{name} endpoint to delete tags from archives
- TagManagementModal component with search, sort, rename, and delete
- Gear icon button next to tag filter dropdown on Archives page
- Fix tag autocompletion in EditArchiveModal using dedicated getTags API
Closes#183
- Path is now optional for power, energy, and state topics
- When path is empty, raw MQTT payload value is used directly
- Energy and state topics no longer fall back to power topic
- Added helper text in UI explaining path is optional
- Fixes energy monitoring not working with separate topics
Closes 173
- Implemented batch STL thumbnail generation API endpoint.
- Added Pydantic schemas for batch thumbnail requests and responses.
- Created service for generating thumbnails from STL files using trimesh and matplotlib.
- Updated file upload and ZIP extraction endpoints to include thumbnail generation option.
- Enhanced frontend to support STL thumbnail generation during file uploads and ZIP extractions.
- Added integration and unit tests for the new thumbnail generation features.
- Updated requirements to include necessary libraries for STL processing.
- Add separate MQTT topics for power, energy, and state monitoring
- mqtt_power_topic, mqtt_power_path, mqtt_power_multiplier
- mqtt_energy_topic, mqtt_energy_path, mqtt_energy_multiplier
- mqtt_state_topic, mqtt_state_path, mqtt_state_on_value
- Support different MQTT topics per data type (e.g., Zigbee2MQTT with
separate power/energy/state topics)
- Individual multipliers for power and energy (e.g., mW→W, Wh→kWh)
- Configurable ON value for state monitoring (e.g., "ON", "true", "1")
- Maintain backward compatibility with legacy mqtt_topic/mqtt_multiplier
- Database migration auto-copies legacy fields to new fields
- Update backup/restore to handle new MQTT fields
- Add backend tests for new MQTT configurations
- Update frontend form with organized Power/Energy/State sections
Closes#173
Backend - X1E model-based queue support:
- Fix 'PrinterState' object has no attribute 'ams_units' error
by accessing AMS data via status.raw_data.get("ams", [])
- Add model name normalization in print_queue.py to convert
"Bambu Lab X1E" or "C13" to canonical "X1E" format
- Add case-insensitive model matching in print_scheduler.py
using func.lower() for database queries
Fixes#162
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 support for MQTT-based smart plugs that subscribe to external MQTT
topics and extract power/energy data from JSON payloads. This enables
integration with Zigbee2MQTT, Shelly, Tasmota discovery, and other
MQTT-enabled energy monitoring devices.
Features:
- New "mqtt" plug type alongside tasmota and homeassistant
- Subscribe to any MQTT topic with configurable JSON paths
- Extract power, energy, and state values using dot notation
- Optional multiplier for unit conversion (mW to W, etc.)
- Monitor-only mode (no on/off control) with teal color scheme
- Reuses existing MQTT broker settings from network configuration
- Energy data included in statistics and per-print tracking
- Full backup/restore support for MQTT plug configurations
Closes#173
- 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>
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
Model-based queue assignment:
- Extract printer_model from sliced 3MF files during upload
- Display sliced-for model in archive view
- New queue mode: assign to "Any [Model]" instead of specific printer
- Scheduler auto-assigns to first idle printer of matching model
- Filament validation: only assign to printers with required filament types loaded
- Waiting reason display shows why jobs are waiting (e.g., "Waiting for filament: Printer1 (needs PLA)")
- "Waiting" status badge (purple) distinguishes from regular "Pending"
Queue notifications (7 new events):
- Job Added: When a job is added to queue
- Job Assigned: When a model-based job is assigned to a printer
- Job Started: When a queue job starts printing
- Job Waiting: When a job is waiting for filament (enabled by default)
- Job Skipped: When a job is skipped due to previous failure (enabled by default)
- Job Failed: When a job fails to start (enabled by default)
- Queue Complete: When all queued jobs finish
Backend changes:
- New columns: print_queue.target_model, print_queue.required_filament_types, print_queue.waiting_reason
- New columns: notification_providers.on_queue_job_* (7 event triggers)
- Notification templates for all queue events
- Scheduler validates filament compatibility before model-based assignment
- Queue API extracts filament types from 3MF when adding model-based items
- Local backup/restore includes queue notification settings
Frontend changes:
- TypeScript interfaces updated for new fields
- Queue page shows waiting reason and "Waiting" badge
- Notification settings includes "Print Queue" section with 7 toggles
Closes#162
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
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
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
- 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
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)
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
Features:
- ZIP file support in File Manager (Issue #121): Upload ZIP files to
automatically extract contents with option to preserve folder structure
- Delete operation loading indicator: Shows progress during folder/file
deletion operations
Fixed:
- Print time stats using actual elapsed time instead of slicer estimates
(Issue #137)
- Skip objects modal overflow with scrollable list for many objects
(Issue #134)
Removed:
- Duplicate badge feature from File Manager (per user request)
Tests:
- Added ZIP extraction backend tests (5 tests)
- Added ConfirmModal loading state frontend tests (5 tests)
Quick Stats "Print Time" now uses actual elapsed time (`completed_at - started_at`) instead of slicer estimates;
cancelled prints only count time actually printed
Closes#137
- Add search parameter to /ha/entities endpoint for searching all entities
- Replace entity dropdown with searchable combobox (type to filter)
- Default shows switch/light/input_boolean; search queries all domains
- Make all three energy sensor dropdowns searchable (Power, Energy Today, Total)
- Each dropdown filters by entity_id or friendly_name
- Shows entity details (name, id, state, unit) in dropdown options
Fixes issue where HA plugs with non-standard entity naming couldn't
find their related power/energy sensors.