Commit Graph
270 Commits
Author SHA1 Message Date
maziggy bb7e8398bc Completely removed telemetry 2026-01-26 09:34:04 +01:00
maziggy 97238644a0 Added missing database migrations 2026-01-26 09:19:28 +01:00
maziggy 3a3f6a1845 Settings API PATCH Method
- Added PATCH support to `/api/settings` for Home Assistant rest_command compatibility

Closes #152
2026-01-25 13:43:47 +01:00
maziggy ec3c47f048 Fix P2S empty archive tiles - add root folder to FTP search paths (Issue #146)
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
2026-01-25 13:33:51 +01:00
maziggy 30537cfa54 Add project import/export with ZIP file support
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)
2026-01-25 13:17:15 +01:00
maziggy 4266049e0c Fix empty AMS slot not recognized (Issue #147)
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
2026-01-25 07:07:36 +01:00
maziggy 6bc1ce8693 Add external link field for archives (Issue #151)
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
2026-01-25 06:47:55 +01:00
maziggy 691fb133b7 Add external network camera support for printers
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
2026-01-24 09:58:45 +01:00
maziggy e0e53cb680 Add multi-file selection and bulk download to printer file browser
- 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
2026-01-24 08:28:03 +01:00
maziggy 8ba04dfa89 Add ZIP folder creation option and improve camera zoom/pan (#121, #132)
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
2026-01-24 08:13:20 +01:00
maziggy 721eab1f67 Fix HA energy sensors not detected due to case-sensitive unit matching
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
2026-01-24 07:39:48 +01:00
maziggy d56206cbac Fix empty archive tiles on P2S printer
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
2026-01-24 07:33:01 +01:00
maziggy 5672d7965a Add recalculate costs button and reprint cost tracking
- 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
2026-01-24 07:05:15 +01:00
maziggy 40c672b1b9 Changed version 2026-01-23 17:57:07 +01:00
maziggy fe35c1d134 Bumped version number 2026-01-23 11:33:49 +01:00
maziggy ec83593456 Merge remote-tracking branch 'origin/main' into 0.1.6b11
# Conflicts:
#	backend/app/api/routes/auth.py
#	frontend/src/contexts/AuthContext.tsx
#	frontend/src/pages/SetupPage.tsx
#	frontend/src/pages/UsersPage.tsx
2026-01-23 11:19:49 +01:00
maziggy f8220e8931 Changed version 2026-01-23 10:59:21 +01:00
maziggy 6225fac398 Multiple fixes and ZIP file support in File Manager
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)
2026-01-23 09:02:25 +01:00
maziggy a6b1c5adbe Print time stats using slicer estimates
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
2026-01-23 08:20:19 +01:00
maziggy 4a3e42db36 Home Assistant smart plug improvements:
- 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.
2026-01-23 07:52:56 +01:00
maziggy 6c5aad1b73 Fix: Mattermost/Slack Webhook Support
Root Cause: The generic webhook sent a JSON payload with custom field names plus timestamp and source fields. Mattermost/Slack webhooks only accept {"text": "..."}
format and reject unknown fields with HTTP 400.

Users just need to select "Slack / Mattermost" from the Payload Format dropdown when configuring their Mattermost webhook.

Closes #133
2026-01-23 07:13:46 +01:00
maziggy 08e4797544 Fix: Internal Model Code Detection for Camera Protocol
Root Cause: P2S (and other newer models) may report their model as internal codes (e.g., "N7" for P2S) rather than display names in MQTT/SSDP responses. The camera code
only checked for display names like "P2S", causing it to incorrectly use the chamber image protocol (for A1/P1) instead of RTSP.

Internal Code Mapping:
BL-P001 → X1/X1C (RTSP)
C13     → X1E    (RTSP)
O1D     → H2D    (RTSP)
O1C     → H2C    (RTSP)
O1S     → H2S    (RTSP)
O1E     → H2D Pro (RTSP)
N7      → P2S    (RTSP)
C11     → P1P    (Chamber)
C12     → P1S    (Chamber)
N2S     → A1     (Chamber)
N1      → A1 Mini (Chamber)

Closes #127
2026-01-23 07:09:22 +01:00
JesseFPV 3a848643c0 Fixed re-auth setup and gitignore node modules 2026-01-22 12:21:07 +01:00
maziggy 0354218657 Add finish photo URL to notification templates (Issue #126)
- Add {finish_photo_url} template variable for print_complete, print_failed,
  print_stopped events
- Photo capture now completes before notification is sent (ensures image exists)
- Add External URL setting in Settings → Network (auto-detects from browser)
- Full URL constructed using external_url setting for external services
- Fix Telegram Markdown parsing error when messages contain URLs
- Add backend schema for external_url setting
- Add unit test for finish_photo_url variable passing
2026-01-22 10:42:20 +01:00
maziggy 0caa68b77f Auto-create Spoolman 'tag' extra field on connect (Issue #123)
The 'tag' extra field is required in Spoolman for storing RFID/UUID
identifiers that link Bambu Lab spools to Spoolman entries. Previously,
users had to manually create this field in Spoolman, causing sync
failures for fresh installations.

Added ensure_tag_extra_field() method to SpoolmanClient that:
- Checks if the 'tag' field exists via GET /api/v1/field/spool/tag
- Creates it via POST if missing

The method is called automatically:
- On app startup when auto-connecting to Spoolman
- When user clicks "Connect" in Spoolman settings
2026-01-22 09:23:40 +01:00
maziggy 01ab2cbb45 Fix filament cost not using default setting
The "Default filament cost (per kg)" setting was being ignored when
calculating filament costs. A hardcoded value of 25.0 was used instead.

All three now read the default_filament_cost setting from the database,
falling back to 25.0 only if the setting doesn't exist.

Users can run "Recalculate Costs" from the Archives page to update
existing archives with the correct default cost.
2026-01-22 09:13:48 +01:00
maziggy d6935c9253 Add Home Assistant energy sensor entity support (Issue #119)
Home Assistant smart plugs can now use separate sensor entities for
energy monitoring, enabling energy tracking for plugs that expose
power/energy data as separate sensors (Tapo, IKEA Zigbee2mqtt, etc.).

Features:
- Configure dedicated power (W), today (kWh), and total (kWh) sensors
- New API endpoint GET /api/v1/smart-plugs/ha/sensors lists available sensors
- Falls back to switch entity attributes if no sensors configured
- Print energy tracking now works for HA plugs (not just Tasmota)

Backend:
- Added ha_power_entity, ha_energy_today_entity, ha_energy_total_entity
  fields to SmartPlug model
- Updated get_energy() to fetch from configured sensor entities
- Added _get_plug_energy() helper to handle both plug types
- Updated backup/restore to include new fields
- Added database migration for new columns

Frontend:
- Added energy sensor dropdowns in AddSmartPlugModal (shown for HA plugs)
- Dropdowns filtered by unit (W/kW for power, kWh/Wh for energy)

Tests:
- Added 4 new integration tests for HA energy sensor functionality

Docs:
- Updated README with new feature
- Updated CHANGELOG with 0.1.6b11 entry
2026-01-22 09:04:40 +01:00
maziggy f334c74d02 Post tasks for PR #117 (Authentication Feature)
Fixes:

  - Fixed is_auth_enabled() returning None instead of False when setting doesn't exist (in both auth.py and routes/auth.py)
  - Fixed get_current_user() crashing when credentials is None
  - Added missing async_session patch in conftest.py for auth tests

  Backup/Restore - Added Users Support
  - Added include_users parameter to backup export
  - Users are exported with username, role, and is_active (passwords excluded for security)
  - Restore creates users with temporary passwords that must be changed

Backend Tests - 16 New Auth Tests
  - test_auth_api.py with tests for:
  - Auth status endpoint
  - Auth setup (enable/disable)
  - Login flow (success, invalid credentials, auth disabled)
  - /me endpoint with/without token
  - User management (list, create, update, delete)
  - Auth disable

Frontend Tests - 6 New Login Tests
  - LoginPage.test.tsx with tests for:
  - Form rendering
  - Input validation
  - Login submission
  - Loading states

Documentation Updates
  - CHANGELOG.md/README.md: Added authentication feature description
  - Website (features.html): Added new "Optional Authentication" section
  - Wiki: Created authentication.md with full documentation
  - Wiki index: Added authentication to features list
2026-01-21 16:41:37 +01:00
maziggy dc30856238 Fixed background tests to support new authentication and user module 2026-01-21 16:25:35 +01:00
maziggy 2e7caf38da Added from future import annotations which defers annotation evaluation so APIKey doesn't need to be imported at runtime. 2026-01-21 16:15:53 +01:00
MartinNYHC a9f340f2c9 Revert "Added optional authentication and user management" 2026-01-21 15:58:24 +01:00
JesseFPV 6e5cc55190 Fixed auth check and conftest 2026-01-21 15:36:39 +01:00
JesseFPV d731cd2a91 Fixed lint errors 2026-01-21 14:50:31 +01:00
JesseFPV 3e1843f834 Updated checks 2026-01-21 14:41:24 +01:00
JesseFPV f8857ba666 Added optional authentication and user management 2026-01-21 14:10:06 +01:00
maziggy a33246a060 Fixed caching for file manager 2026-01-21 06:06:47 +01:00
maziggy 576734c897 Fixed frontend/backend tests 2026-01-20 17:50:16 +01:00
maziggy d32059ab78 - Add rename functionality for files and folders:
- New RenameModal component with validation
  - Backend endpoint supports filename updates (rejects path separators)
  - Context menu "Rename" option in grid and list views
  - Inline rename button in list view actions
- Add Print button to multi-selection toolbar:
  - Appears when exactly one sliced file is selected
  - Opens full PrintModal with plate selection and options
  - Add to Queue button now uses Clock icon for clarity
- Improve mobile/PWA accessibility:
  - Three-dot menu button always visible on mobile (md:opacity-0)
  - Selection checkbox always visible on touch devices
  - Better experience for PWA users on tablets and phones

Closes #94
2026-01-20 17:39:07 +01:00
maziggy e1224316a7 Add per-printer AMS mapping for multi-printer selection
- New useMultiPrinterFilamentMapping hook for parallel printer status fetching
- Per-printer custom slot configuration with "Custom mapping" checkbox
- Auto-configure using RFID data to match filaments by type/color
- Match status indicator (exact/partial/missing) under each printer
- Re-read button to refresh loaded filaments
- New setting: "Expand custom mapping by default" in Settings → Filament
- FilamentMapping component now accepts defaultExpanded prop

Frontend:
- PrinterSelector: Inline mapping editor for each selected printer
- PrintModal: Fetches settings, auto-expands mapping when setting enabled
- SettingsPage: Toggle for per_printer_mapping_expanded

Backend:
- Added per_printer_mapping_expanded to AppSettings schema
- Added boolean parsing in settings routes
- Added integration tests for new setting

Closes #104
2026-01-20 16:59:18 +01:00
maziggy 90249d2367 Adds a live log viewer component to the Support & Troubleshooting section
that allows viewing and filtering application logs in real-time.
Features:
- Start/Stop live streaming with 2-second auto-refresh
- Filter by log level (DEBUG, INFO, WARNING, ERROR)
- Text search across messages and logger names
- Clear logs with one click
- Expandable multi-line log entries (stack traces, etc.)
- Auto-scroll to follow new entries

Closes #87
2026-01-20 16:11:45 +01:00
maziggy 02f6de4adc New Features:
- Print from File Manager with plate selection, AMS mapping, and print options. Closes #94
- Add to queue without creating archive (reduces clutter)
- Queue displays library file name, thumbnail, and print time

Fixes:
Queue items from File Manager now reference library files directly instead of
creating archives upfront. Archives are created automatically when prints start.
2026-01-20 15:37:20 +01:00
maziggy 3c9a03cadc Add camera view mode setting for window or embedded display
Users can now choose how camera streams open via Settings → General → Camera:
- "New Window" (default): Opens camera in a separate browser window
- "Embedded": Shows camera as a draggable, resizable overlay on the main screen

The embedded camera viewer features:
- Draggable header to reposition anywhere on screen
- Resizable via bottom-right corner handle
- Position and size persist to localStorage across sessions
- Minimize/maximize toggle
- Auto-reconnect with exponential backoff on stream errors
- Stall detection for frozen streams

Closes #105
2026-01-20 12:57:22 +01:00
maziggy 494da46b09 **Configure AMS Slot**
Manually configure AMS slots for third-party or generic filaments:
1. Hover over an AMS slot on the printer card
2. Click the menu button (:material-dots-vertical:) that appears
3. Select **Configure Slot**
4. Choose a filament preset from your Bambu Studio cloud presets
5. Select a matching K profile (pressure advance calibration)
6. Optionally set a custom color using the color picker
7. Click **Configure Slot** to apply

**Color Picker Features:**
- Enter custom hex codes or color names (e.g., "brown", "FF8800")
- Live preview of selected color
- Expandable color picker in Configure AMS Slot modal:
  - 8 basic colors shown by default
  - 24 additional colors available via expand button
- Tests for ConfigureAmsSlotModal component
- Tests for AMS change callback
- Updated README with AMS slot configuration feature
- Wiki documentation for Configure AMS Slot feature

- Multi plate issue where plate names showed incorrect. #93
- Items from Queue end up as "source" files in archive. #107
- Added env variable support to change network port. #108
  Docs -> https://wiki.bambuddy.cool/getting-started/docker/?h=port#custom-port
2026-01-20 11:57:09 +01:00
maziggy 9bfb969169 Added nozzle indicator for multi nozzle printers 2026-01-19 15:29:15 +01:00
maziggy 43d167abd3 Changed version 2026-01-19 13:44:15 +01:00
maziggy 5c7768401d Changed version; Updated CHANGELOG 2026-01-19 13:29:37 +01:00
maziggy d48abe0f6a Add File Manager and enhanced Queue features
File Manager:
- Add full File Manager page for browsing local library files
- Implement folder hierarchy with create/rename/delete operations
- Add file uploads with drag-and-drop support
- Enable adding sliced files directly to print queue
- Add linked folders with external path mounting

Queue Enhancements:
- Add plate selection for multi-plate 3MF files
- Add print options (bed levelling, flow calibration, vibration
  calibration, layer inspection, timelapse, use AMS)
- Fix print_count increment to only occur on actual prints

Testing:
- Add backend integration tests for library API (15 tests)
- Add backend integration tests for queue print options (8 tests)
- Add frontend tests for EditQueueItemModal (10 tests)
- Suppress console noise in frontend test suite

Closes #94
2026-01-19 13:29:37 +01:00
maziggy b2831d09a2 Frontend ESLint Warnings (8 fixed)
┌─────────────────────────┬───────────────────────────────────────────────────────────┐
  │          File           │                            Fix                            │
  ├─────────────────────────┼───────────────────────────────────────────────────────────┤
  │ CameraPage.tsx:75       │ Copy imgRef.current to a variable before cleanup          │
  ├─────────────────────────┼───────────────────────────────────────────────────────────┤
  │ useWebSocket.ts:121     │ Add processMessageQueue to useCallback dependencies       │
  ├─────────────────────────┼───────────────────────────────────────────────────────────┤
  │ SpoolmanSettings.tsx:89 │ Add eslint-disable comment (intentional debounce pattern) │
  ├─────────────────────────┼───────────────────────────────────────────────────────────┤
  │ MQTTDebugModal.tsx:95   │ Wrap logs in useMemo to prevent recreating on each render │
  ├─────────────────────────┼───────────────────────────────────────────────────────────┤
  │ Layout.tsx:166          │ Wrap navItemsMap and extLinksMap in useMemo               │
  ├─────────────────────────┼───────────────────────────────────────────────────────────┤
  │ KProfilesView.tsx:715   │ Wrap getProfileKey in useCallback                         │
  ├─────────────────────────┼───────────────────────────────────────────────────────────┤
  │ GcodeViewer.tsx:171     │ Add eslint-disable comment (intentional behavior)         │
  └─────────────────────────┴───────────────────────────────────────────────────────────┘
  Docker Integration Test Fix

  The /api/v1/settings endpoint was returning 404 because:
  1. The route was defined at /settings/ (with trailing slash)
  2. Curl without -L doesn't follow redirects
  3. The catch-all route was intercepting API paths

  Fixes:
  - Added routes for both with and without trailing slash in settings.py and notification_templates.py
  - Updated catch-all in main.py to raise proper HTTPException for API routes

  Test Results

  - Frontend lint: 0 errors, 0 warnings
  - TypeScript: No errors
  - Backend unit tests: 264 passed
  - Backend integration tests: 309 passed
2026-01-19 13:29:37 +01:00
maziggy af0dad11ec Add multi-plate 3MF plate selection for reprinting (Issue #93)
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
2026-01-19 13:29:37 +01:00
maziggy 3a2ec8056c Fix multi-plate 3MF metadata extraction (Issue #92)
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
2026-01-19 13:29:37 +01:00