The FTP code called prot_p() (protected data channel) for all printers,
but for A1/A1 Mini it didn't wrap the data connection in SSL. This
mismatch caused an immediate EOFError - server expected encrypted data
but received plain data.
Fix:
- Use prot_c() (clear/unencrypted data channel) for A1/A1 Mini
- Use prot_p() (protected/encrypted data channel) for X1C/P1S/etc
- Removed non-functional ftplib._SSLSocket = None workaround
A1/A1 Mini: control channel encrypted (implicit TLS), data channel clear
X1C/P1S/etc: both channels encrypted with SSL session reuse
Closes#271
When auth was enabled, API keys were not accepted by the permission
checking functions. Only JWT tokens were validated.
API keys are accepted via two methods:
- X-API-Key header with the key value
- Authorization: Bearer header (keys starting with "bb_" are treated
as API keys, others as JWT tokens)
Closes#270
Issue #245: H2D Pro print errors (extrusion motor overloaded)
- H2D series requires integer format (0/1) for boolean fields
- Other printers (X1C, P1S, A1) require actual booleans (true/false)
- Added model detection to use correct format per printer type
- Affected fields: timelapse, bed_leveling, flow_cali, vibration_cali,
layer_inspect, use_ams
Closes#245
- Mask HMS error codes to 16 bits to fix malformed display
(H2D sends code 0x2001B which displayed as "0C00_2001B" instead of "0C00_001B")
- Filter notifications to severity >= 2, skipping informational messages
(H2D sends severity 1 camera status that isn't a real error)
Removed P1S and P1P from SKIP_SESSION_REUSE_MODELS
- These printers use vsFTPd which requires SSL session reuse on data channel
- Only A1/A1 Mini should skip session reuse (they have issues with SSL on data channel)
- P1S/P1P were incorrectly added in commit 9969005, causing EOFError on FTP upload
Closes#266
The tray_info_idx field is a filament TYPE identifier (e.g., "GFA00" for
generic PLA), not unique per spool. When multiple AMS trays are loaded
with the same filament type, the previous code used find() which always
returned the first match regardless of color.
Now checks if tray_info_idx is unique among available trays:
- If unique: use that tray as definitive match (existing behavior)
- If not unique: fall back to color matching among matching trays
Fixed in both backend (print_scheduler.py) and frontend (useFilamentMapping.ts).
Closes#245
- SSDP proxy for cross-network setups: select slicer network interface for automatic printer discovery via SSDP relay
- FTP proxy now listens on privileged port 990 (matching Bambu Studio expectations) instead of 9990
- For systemd: requires `AmbientCapabilities=CAP_NET_BIND_SERVICE` capability
- Automatic directory permission checking at startup with clear error messages for Docker/bare metal
When multiple AMS trays have the same filament type and color, Bambuddy
now uses the tray_info_idx attribute from the 3MF file to identify the
exact spool selected during slicing. This ensures the correct tray is
used rather than just picking the first match.
Matching priority: tray_info_idx > exact color > similar color > type-only
Closes#245
When multiple AMS trays have the same filament type and color, Bambuddy
now uses the tray_info_idx attribute from the 3MF file to identify the
exact spool selected during slicing. This ensures the correct tray is
used rather than just picking the first match.
Matching priority: tray_info_idx > exact color > similar color > type-only
Closes#245
The filament_used_grams field already contains the total filament for
the entire print job (all items combined). The code was incorrectly
multiplying this value by quantity, causing inflated filament totals.
Example: A print with 26 objects using 126g total was being calculated
as 126g * 26 = 3,276g instead of the correct 126g.
Fixes:
- backend/app/api/routes/archives.py: Archive stats endpoint
- backend/app/api/routes/metrics.py: Prometheus metrics endpoint
- frontend/src/components/FilamentTrends.tsx: Trends chart calculations
Closes#229
- Added query to fetch library file details in PrintModal
- Updated backend FileResponse schema to include metadata fields (print_name, print_time_seconds, filament_used_grams, sliced_for_model)
- Updated backend get_file endpoint to extract and return metadata fields
- Updated frontend LibraryFile interface to include metadata fields
- Now slicedForModel is properly extracted from both archives and library files
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
Addresses reports of files being automatically reprinted hours after
the original print completed. The root cause was a race condition where
the queue item status was updated to "printing" AFTER the print command
was sent, allowing stuck "pending" items to be re-triggered on restart.
Changes:
- Set status to "printing" BEFORE sending print command to prevent
re-triggering if backend crashes after print starts
- Add 24-hour expiration for stale pending queue items
- Add duplicate prevention: skip archives completed within last 4 hours
Trade-off: If backend crashes after status update but before print
command, item will be stuck in "printing" without actually printing.
This is safer than accidentally reprinting and wasting filament.
Bambu Studio converts spaces to underscores when saving files to the
printer, but MQTT reports the original name with spaces. This caused
FTP downloads to fail with "550 Failed to open file" because we were
searching for "Battery Storage_giesela.gcode.3mf" but the actual file
was "Battery_Storage_giesela.gcode.3mf".
Changes:
- Add underscore variants to direct download path attempts
- Normalize spaces/underscores in fallback directory search
- Apply fix to archive download, cover extraction, and objects reload
Closes#218
Introduces a new "Proxy Mode" for the Virtual Printer that enables
remote printing from anywhere in the world without VPN, port forwarding,
or Bambu Cloud dependency.
Bambuddy acts as a TLS relay between a remote slicer (Bambu Studio/
OrcaSlicer) and the local Bambu Lab printer:
Remote Slicer → Internet → Bambuddy Server → Local Network → Printer
The slicer connects to Bambuddy using the real printer's serial number
and access code. Bambuddy authenticates and relays all FTP (file transfer)
and MQTT (commands/status) traffic with end-to-end TLS encryption.
- No port forwarding required - printer stays safely on local network
- No VPN needed - connect from coffee shops, hotels, work, anywhere
- No Bambu Cloud dependency - fully self-hosted solution
- End-to-end TLS encryption on FTP (port 9990) and MQTT (port 8883)
- Works with Bambu Studio and OrcaSlicer
- Uses real printer credentials for authentication
- Automatic printer selection from connected printers
- Add SlicerProxyManager class for TLS relay (tcp_proxy.py)
- TLS termination with auto-generated certificates
- Concurrent FTP and MQTT proxy servers
- Connection lifecycle management with proper cleanup
- Extend VirtualPrinterManager with proxy mode support
- New 'proxy' mode alongside archive/review/queue modes
- Target printer selection and credential management
- Add proxy configuration endpoints to settings API
- Add permission checks for proxy endpoints
- Add Proxy Mode card to Virtual Printer settings
- Target printer dropdown for proxy destination
- Real-time proxy status display (ports, target, running state)
- Full i18n support (English, German)
- Add network architecture diagram
- Add proxy mode section to README
- Add comprehensive guide to wiki
- Add prominent feature section to website
- Backend unit tests for SlicerProxyManager
- Backend unit tests for proxy mode configuration
- Frontend tests for proxy mode UI components
Closes#207#170
Both frontend and backend were blocking printers that already had any
smart plug linked, preventing users from adding multiple HA entities
to the same printer.
Changes:
- Frontend: Only filter out printers with existing Tasmota plugs
- Backend: Only check for duplicate Tasmota plugs on create/update
- HA entities (switches, scripts, lights, etc.) can now be linked
multiple times to the same printer for different automations
- Tasmota plugs remain limited to one per printer (physical device)
- Restored "Show on Printer Card" toggle for HA entities
- Fixed printer card only showing script.* entities; now shows all
HA entities with the toggle enabled
- HA entities now default to auto_on=False and auto_off=False
- Printer cards now update immediately when HA entities change
Closes#214
Load project relationship in ArchiveService.get_archive() alongside
created_by. Async SQLAlchemy doesn't support lazy loading, so project
must be eagerly loaded for archive_to_response() to access project.name.
The filament statistics were under-reporting totals because the quantity
field was not being multiplied with filament_used_grams. When users
printed multiple items (quantity > 1), only the base filament amount
was counted instead of the total.
Closes#229
TOTP (Two-Factor Authentication):
- Detect TOTP vs email verification from Bambu API loginType response
- Use dedicated TFA endpoint on bambulab.com (not api.bambulab.com)
- Include browser-like headers to bypass Cloudflare protection
- Extract token from JSON response or cookies
- Frontend shows appropriate messages for each verification type
- Added i18n translations for TOTP UI (en, de, ja)
Closes#182
Proxy mode changes:
- Replace transparent TCP proxy with TLS-terminating proxy
- Slicer connects to Bambuddy cert, Bambuddy connects to printer
- Use real printer's serial number for SSDP and certificate
- This ensures MQTT topic subscriptions match the real printer
The proxy now:
1. Accepts TLS from slicer using Bambuddy's certificate
2. Opens TLS connection to real printer
3. Forwards decrypted data bidirectionally
Also: Complete i18n localization for VirtualPrinterSettings component
When a spool is already linked in Spoolman, the FilamentHoverCard now shows
"Open in Spoolman" button instead of "Link to Spoolman". This allows users
to quickly navigate to the spool's page in Spoolman for editing.
Changes:
- Add GET /api/v1/spoolman/spools/linked endpoint returning tag->spool_id map
- FilamentHoverCard shows "Open in Spoolman" when linkedSpoolId is set
- "Link to Spoolman" only shows when spool is not linked
- Fix unlinked spools detection to strip JSON quotes from empty tags
- Add toast notifications for link success/failure
- Invalidate linked-spools query after linking
- Add backend tests for linked spools endpoint
- Add frontend tests for LinkSpoolModal
Closes#210
Add explanatory comment for CodeQL alert about clear-text storage
of JWT secret. This is intentional and secure:
- JWT secrets must be readable by the application
- File permissions set to 0600 (owner read/write only)
- Standard practice for self-hosted apps (same as .env files)
The alert should be dismissed in GitHub Security tab as "Won't fix".
The File Manager (Library) backend had no permission enforcement - endpoints were returning data to any authenticated user regardless of their group permissions.
Closes#224