Commit Graph
512 Commits
Author SHA1 Message Date
MartinNYHC 67f91d94de v0.2.2.2 (#830)
v0.2.2.2 (#830)
2026-03-27 09:27:47 +01:00
maziggy 4fa1c2b08a Add missing migration for spoolbuddy update_status columns
The OTA update feature added update_status and update_message to the
  SpoolBuddyDevice model but no ALTER TABLE migration, causing
  "no such column: spoolbuddy_devices.update_status" on existing databases.
2026-03-22 14:13:12 +01:00
maziggy 6b4bc99d31 Suppress false-positive bandit B104 in VP proxy comparisons
Two "0.0.0.0" string comparisons (not binds) in tcp_proxy.py
  triggered B104. Added targeted # nosec B104 comments.
2026-03-22 13:45:59 +01:00
maziggy 988429b6e6 Set version 2026-03-22 13:29:50 +01:00
maziggy cbecdd18f4 Bump flatted 3.4.1 → 3.4.2 to fix prototype pollution
Fixes GHSA-rf6f-7fwh-wjgh (CWE-1321). Dev-only dependency via
  eslint → file-entry-cache → flat-cache → flatted.
2026-03-22 13:26:50 +01:00
maziggy 407c9f84cf Bump pyOpenSSL and pyasn1 to fix 3 CVEs
pyOpenSSL 25.3.0 → 26.0.0 (CVE-2026-27448, CVE-2026-27459)
  pyasn1 0.6.2 → 0.6.3 (CVE-2026-30922)

  No breaking changes — Python 3.7 drop is irrelevant (we use 3.13),
  cryptography >=46.0.0 requirement already satisfied (we have 46.0.5),
  and we don't use set_tlsext_servername_callback (the behavioral change).
2026-03-22 13:24:36 +01:00
maziggy 311a14e7ec Improve SpoolBuddy update UX: auto-check and remove beta toggle
The SpoolBuddy layout now auto-checks for daemon updates every 5
  minutes and shows "Update available: v{version}" in the status bar.
  Removed the beta toggle since SpoolBuddy follows Bambuddy's release
  channel. The daemon version is now read from backend APP_VERSION
  instead of a stale hardcoded string.
2026-03-22 13:15:44 +01:00
maziggy 18700cf5da Fix SpoolBuddy daemon reporting stale version in update check
The daemon had a hardcoded __version__ = "0.2.2b1" that was never
  bumped, causing the update check to always show an update available.
  Changed to read APP_VERSION from backend/app/core/config.py at import
  time so the daemon version stays in sync automatically.
2026-03-22 13:08:45 +01:00
maziggy cf2203914d [Feature] SpoolBuddy OTA updates via Bambuddy UI
SpoolBuddy devices can now be updated from Settings → Updates without
  SSH access. The daemon picks up an "update" command via its existing
  heartbeat, runs git fetch/reset + pip install, reports progress back
  to the backend, then exits for systemd to restart with the new code.

  Backend: update_status/update_message fields, trigger + status endpoints
  Daemon: _perform_update() handler, report_update_status() API method
  Frontend: "Apply Update" button with live progress in UpdatesTab
2026-03-22 12:40:25 +01:00
maziggy 750accb17d Fix queue print command not reaching printer on reconnect (#778)
When targeting a specific printer, the scheduler's power-on-wait loop
  created new MQTT clients on each attempt. Each new client re-tried the
  request topic subscription, which some brokers (e.g. A1) reject by
  disconnecting. This caused a 170s thrash loop leaving the connection
  fragile, so the eventual print command silently failed to reach the
  printer.

  Cache request topic support per serial number at the class level so
  new client instances inherit the knowledge and skip the subscription.
2026-03-22 08:17:53 +01:00
maziggy 1b3faca4c7 Add checkboxes to select plates to queue (#777)
Multi-plate 3MF files now support selecting a subset of plates to queue
  via checkboxes, instead of the binary "one plate" or "all plates" toggle.
  In add-to-queue mode, each plate gets a checkbox for multi-select with a
  Select All / Deselect All toggle. Reprint and edit modes remain single-select.
2026-03-22 07:51:47 +01:00
maziggy 7b88b50d27 Fix AMS slot search still showing wrong preset for PLA Silk (#681)
The saved preset bypassed the search filter entirely, so when a slot's
  DB mapping was stale (e.g. previously Matte, now physically Silk), the
  old preset always appeared regardless of search query. Remove the search
  bypass — saved/current presets still bypass the printer model filter but
  must match the search text like all other presets.
2026-03-21 14:08:30 +01:00
maziggy 0db6541664 [Feature] Improve HMS error visibility on Printers page (#772)
Add visual indicators so printers with HMS errors stand out in large
  print farms:

  - Red "Problem" counter in the status summary bar
  - Status pip turns red (fatal/serious) or amber (warning) for HMS errors
  - Progress bar turns amber when a print is paused
  - Status sort prioritizes printers with HMS errors at the top
2026-03-21 09:47:50 +01:00
maziggy 488f66310f [Fix] Preserve AMS spool assignments across printer restart (#765)
When a printer shuts down it sends a final MQTT message with
  tray_exist_bits=0 and power_on_flag=false. The tray_exist_bits
  clearing code processed this all-zero value, wiping every AMS
  slot's filament data. On reconnect, the auto-unlink check saw
  empty tray data (no color, no type) and deleted all spool
  assignments as "fingerprint mismatch".

  Fix: skip tray_exist_bits slot clearing when power_on_flag is
  false. Defaults to true when absent for backwards compatibility.

  Adds 3 regression tests covering shutdown preservation, genuine
  removal still working, and missing power_on_flag fallback.
2026-03-20 16:28:45 +01:00
maziggy dc4d77b93a [Feature] Redesign bug report debug log capture flow
Replace fixed 30-second debug log collection with an interactive
  3-step flow: start logging, reproduce the issue, stop & submit.
  Users now control timing instead of racing a countdown.

  Backend: split _collect_debug_logs() into POST /start-logging and
  POST /stop-logging endpoints; add debug_logs field to submit request.
  Frontend: 3-step progress indicator with elapsed timer, pulsing
  active state, and 5-minute auto-stop. Updated all 7 locale files.
2026-03-20 14:18:24 +01:00
maziggy e82362ac65 [Feature] Add spool rotation option for AMS drying
Add a "Rotate spool during drying" checkbox to the manual drying popover
  for AMS 2 Pro and AMS-HT units. The firmware-level rotate_tray field was
  already sent (hardcoded to false) — this makes it user-configurable.
  The checkbox defaults to unchecked and resets each time the popover opens.
  Firmware silently disables rotation if filament is currently loaded.
2026-03-20 12:14:44 +01:00
maziggy 35ce075486 [Fix] Suppress spurious "waiting for filament" notification when printers are busy (#753)
When all matching printers were busy and a job was queued with ASAP
  timing, the scheduler immediately fired a "Job Waiting for Filament"
  notification even though the job was just waiting for a printer to
  finish — no user action required.

  Added _is_busy_only() check to skip the waiting notification when the
  only reason is "Busy". Notifications still fire for actionable reasons
  (missing filament, offline, wrong color). Also renamed the default
  notification template title to "Queue Job Waiting" and updated
  descriptions across all 7 locales.
2026-03-20 11:34:23 +01:00
maziggy 664fc86e3f [Fix] File rename preserves extension in File Manager (#751)
Renaming a file in the File Manager included the extension in the
  editable text, letting users accidentally strip it and break the file.
  The rename modal now separates the base name from the extension
  (.3mf, .gcode, .gcode.3mf), showing the extension as a non-editable
  gray suffix and re-appending it on save.
2026-03-20 11:18:28 +01:00
maziggy f6a85031e6 [Debug] Virtual Printer proxy: diagnostic port probing for A1 (#757)
A1/A1 Mini printers fail to connect through VP proxy mode while
    X1C/P2S/H2C work fine with identical transparent TCP proxy code.
    Root cause unknown — the proxy is model-agnostic, so the failure
    suggests BambuStudio uses a different connection flow for A1 models
    that hits ports we don't proxy.

    Add diagnostic probe listeners on ports 21, 80, and 443 on each
    proxy VP's dedicated bind IP. If the slicer connects to any of
    these un-proxied ports, a WARNING is logged so debug logs and
    tcpdump can reveal what's missing.
2026-03-20 10:52:42 +01:00
maziggy 332a7c6ac8 [Fix] Virtual Printer proxy: transparent TCP for X1C/X1 compatibility (#757)
The closed-source bambu_networking DLL validates TLS connection parameters
  and rejects connections where the certificate doesn't match the printer's
  real BBL CA certificate. The TLS-terminating proxy presented Bambuddy's
  own certificate, causing X1C/X1 prints to silently fail after verify_job.

  Switch to transparent TCP proxying for FTP, FileTransfer, Camera, and FTP
  data — only MQTT remains TLS-terminated (required for IP rewriting). The
  slicer now gets end-to-end TLS directly with the printer's real certificate.

  Changes:
  - SlicerProxyManager uses TCPProxy for FTP (990), FileTransfer (6000),
    Camera (322), and pre-listens on FTP data ports (50000-50100)
  - Only MQTT (8883) uses TLSProxy for IP rewriting
  - Remove debug logging from MQTT and FTP proxy code
  - Fix install.sh missing AmbientCapabilities=CAP_NET_BIND_SERVICE
  - Update module docstring, migration docs, README proxy description
  - Add tests verifying transparent proxy architecture
2026-03-19 15:43:11 +01:00
maziggy 1b1f58fc88 [Fix] Virtual Printer proxy mode fails on isolated networks (#757)
When the slicer and printer are on different VLANs, Bambu Studio could
  not send prints through the proxy because the printer's real IP leaked
  through MQTT payloads, the bind protocol forwarded the real printer's
  identity, file transfer and camera ports were not proxied, and FTP
  data connections raced the TLS handshake on zero-byte uploads.

  - Rewrite IP addresses in MQTT PUBLISH payloads (string + integer)
    with proper packet framing and cross-chunk buffering
  - Respond to bind/detect with VP identity via BindServer
  - Add TLS proxies for port 6000 (file transfer) and 322 (RTSP camera)
  - Buffer slicer FTP data during printer connection setup
  - Advertise configured VP name in SSDP proxy
  - Add cross-subnet SSDP wildcard listener for VPN setups
  - Register UserEmailPreference model in models/__init__.py
  - Add 11 unit tests for MQTT rewrite, IP conversion, SSDP name
2026-03-19 11:10:22 +01:00
maziggy 0b2b81a34d [Fix] Virtual Printer proxy mode fails on isolated networks (#757)
When the slicer and printer are on different VLANs, Bambu Studio could
  not send prints through the proxy because the printer's real IP leaked
  through MQTT payloads, the bind protocol forwarded the real printer's
  identity, the port 6000 file transfer tunnel was not proxied, and FTP
  data connections raced the TLS handshake on zero-byte uploads.

  - Rewrite IP addresses in MQTT PUBLISH payloads (string + integer)
    with proper packet framing and cross-chunk buffering
  - Respond to bind/detect with VP identity via BindServer
  - Add TLS proxy for port 6000 (file transfer tunnel)
  - Buffer slicer FTP data during printer connection setup
  - Advertise configured VP name in SSDP proxy
  - Add cross-subnet SSDP wildcard listener for VPN setups
  - Register UserEmailPreference model in models/__init__.py
  - Add 11 unit tests for MQTT rewrite, IP conversion, SSDP name
2026-03-19 11:03:10 +01:00
maziggy dfb995bfe9 [Fix] Remove incorrect "Lubricate Carbon Rods" maintenance task (#755)
Carbon rods use plain bearings — lubricating them degrades print quality.
  Removed the lubrication task from defaults; only "Clean Carbon Rods"
  remains. Existing entries are auto-removed on next startup via
  ensure_default_types(). Updated wiki link mapping and tests.
2026-03-19 08:40:24 +01:00
maziggy c5a0651172 Fix AMS slot search showing unrelated filament profiles (#681)
When searching for a non-existent profile in the AMS slot config modal,
  presets matching the current slot's tray_info_idx bypassed the search
  filter, showing e.g. all "Generic PLA" variants instead of no results.
  Narrow the search bypass to only the exact saved preset — the broader
  trayIdx match still bypasses the model filter as intended.
2026-03-19 08:29:03 +01:00
maziggy 00bc1e214a Add print command response verification for #737
After sending a print command via MQTT, monitor whether the printer's
  gcode_state changes within 15 seconds. If not, log a warning visible in
  support packages. Addresses silent command drops observed on P1S firmware
  01.09.01.00 where the printer ignores project_file commands while
  continuing to send status updates.
2026-03-19 08:14:05 +01:00
maziggy da61a1caa5 Updated CHANGELOG 2026-03-18 18:13:59 +01:00
maziggy 0e712c72a1 [Feature] Add quick print speed control to printer card (#256)
Add a speed control badge to the printer monitoring card controls row
  that lets users switch between Silent (50%), Standard (100%), Sport
  (124%), and Ludicrous (166%) presets during active prints. The badge
  displays a gauge icon with the current speed percentage, always visible
  but disabled when idle. Includes backend endpoint, optimistic UI
  updates, i18n for all 7 locales, and full test coverage.
2026-03-18 11:13:27 +01:00
maziggy 96966cd3d2 [Feature] Add spool name column and filter to filament inventory (#740)
Add a "Spool" column to the filament inventory table that displays
  the spool catalog entry name associated with each spool. The column
  is hidden by default and can be enabled via the column visibility
  menu. Also add a spool name filter dropdown next to the brand filter,
  shown when any spools have catalog entries assigned. No backend
  changes needed — catalog data is fetched and joined on the frontend.
2026-03-18 10:34:15 +01:00
maziggy e149fa23d4 [Fix] Ntfy notifications fail with non-ASCII printer names (#742)
Ntfy notifications with camera snapshots failed when the printer name
  or filename contained non-ASCII characters. httpx enforces ASCII
  encoding on string header values, but the Title and Message headers
  can contain printer names with accented letters or CJK characters.
  Encode these header values as UTF-8 bytes, which ntfy handles correctly.

  Test notifications were unaffected because they use a hardcoded ASCII
  title and no image attachment.
2026-03-18 09:39:46 +01:00
maziggy 82d329d85c [Fix] Virtual Printer FTP routed to wrong VP with different access codes (#735)
When running multiple virtual printers with different access codes on
  separate bind IPs, FTP connections were always routed to the wrong VP.

  Root cause: the iptables REDIRECT rule (990→9990) rewrites the
  destination IP to the incoming interface's primary address. With Linux's
  weak host model (arp_filter=0), packets for secondary IPs arrive on the
  primary interface, and REDIRECT sends them all to the first VP's FTP
  server. MQTT was unaffected because port 8883 had no redirect.

  Fix: FTP server now binds directly to port 990 (standard implicit FTPS),
  eliminating the iptables redirect entirely. Requires CAP_NET_BIND_SERVICE
  (already set in the systemd service file and Docker image).

  Also removed a global asyncio set_exception_handler() in the MQTT server
  that was overwritten by each VP instance, causing spurious "Unhandled
  exception in client_connected_cb" errors on startup.

  Changes:
  - FTP_PORT: 9990 → 990 (ftp_server.py)
  - Removed set_exception_handler() from MQTT server
  - Updated Dockerfile, docker-compose.yml port mappings
  - Deprecated --redirect-990 in install script
  - Updated wiki: removed iptables instructions for all platforms
  - Added migration guide (docs/migration-vp-ftp-port.md)
  - Added unit tests for port constant and no-global-state invariant
2026-03-18 09:04:31 +01:00
maziggy dcdebef9a8 [Fix] Spool assignment UI shows wrong filament preset name (#681)
After assigning a spool to an AMS slot, the Bambuddy UI could show the
  wrong filament preset (e.g. "Bambu PLA Matte" instead of "Bambu PLA
  Silk") even though the printer was configured correctly.

  Two bugs:
  1. AssignSpoolModal (PrintersPage hover card path) never saved the slot
     preset mapping to the DB, so the display fell back to the old/stale
     mapping from a previous manual configuration.
  2. AssignToAmsModal (SpoolBuddy path) constructed the preset name from
     spool.material + spool.subtype ("PLA Silk") instead of using the
     authoritative spool.slicer_filament_name ("Bambu PLA Silk").

  Fix: the backend now saves the slot preset mapping in assign_spool()
  after successful MQTT configuration, using slicer_filament_name as the
  display name. This covers both frontend paths and ensures the correct
  name is always stored.
2026-03-18 08:12:08 +01:00
maziggy b2335a2592 Added VP name prefix (e.g. [Virtual - X1C]) to all FTP and MQTT
log lines so issues can be traced to a specific virtual printer, and
  demoted FTP protocol chatter from info to debug.
2026-03-17 17:36:47 +01:00
maziggy 3d09fe0cd9 [Security] Remove plaintext password logging from VP FTP server
FTP PASS commands were logged with the plaintext password visible in
  log files. Since support packages include logs and are shared publicly
  on GitHub issues, this exposed user access codes. Now redacted as
  PASS ********.
2026-03-17 17:26:10 +01:00
maziggy dbe86968b0 [Fix] Print complete notification not firing (#736)
Print complete notifications were chained behind the finish photo
  capture task with no timeout. If photo capture hung, the notification
  would never send. Added a 45-second timeout so notifications always
  fire regardless of photo outcome.

  Also added diagnostic logging to MQTT state detection and upgraded
  notification error logging to include stack traces for easier
  debugging.
2026-03-17 17:00:32 +01:00
maziggy 6be5fa6632 [Fix] Camera window overlapping modals (#738)
Floating camera viewer used z-50, same as all modals, causing it to
  render on top of dialogs like Assign Spool. Lowered to z-40 so modals
  always stack above the camera window.
2026-03-17 16:40:16 +01:00
maziggy 4f617c21e1 [Fix] X1C Virtual Printer not accepting sends (#735)
X1C and X1 virtual printers used legacy SSDP model codes
  (3DPrinter-X1-Carbon, 3DPrinter-X1) that BambuStudio doesn't
  recognize, causing "incompatible printer preset" errors when
  sending prints. Changed to the correct codes (BL-P001, BL-P002)
  that real printers report via SSDP.

  Also fixed proxy mode auto-inherit storing printer display names
  (e.g. "X1C") instead of SSDP codes, by adding a resolution layer
  that maps display names to model codes.

  DB migration auto-converts existing VPs on startup.
2026-03-17 16:25:31 +01:00
maziggy fe3c1983af Add camera image rotation option (#672)
Per-printer camera rotation (0°/90°/180°/270°) for cameras mounted
  in portrait or upside-down. CSS rotation for live views, Pillow
  rotation for notification snapshots. Setting visible in external
  camera config when enabled.
2026-03-17 13:59:01 +01:00
maziggy aeae5cfa23 Reformat AMS drying presets table (#732)
Group columns by AMS type (AMS 2 Pro, AMS-HT) with inline °C and h
  unit labels next to each input instead of separate column headers.
2026-03-17 13:36:39 +01:00
maziggy 98cb88a06b Fix beta updates shown when disabled (#731)
Daily beta build tags (e.g. v0.2.3b1-daily.20260316) were not detected
  as prereleases because parse_version() only checked the last
  dot-separated segment for letters. The daily date suffix is purely
  numeric, so it passed the stable release check. Now checks the entire
  version string for prerelease markers.
2026-03-17 13:20:25 +01:00
maziggy a4006408a2 Fix white filament color swatches invisible in light theme (#726)
Changed filament color circle borders from border-white/20 to
  border-black/20 across all views so white spools are distinguishable
  against light backgrounds.
2026-03-17 13:08:04 +01:00
maziggy 11610a5b48 Compact assign spool modal grid layout (#725)
- Change spool list from vertical to 3-column grid (2-col on small screens)
  - Widen modal from max-w-md to max-w-2xl
  - Increase scroll area from max-h-64 to max-h-96
  - Show compact cards with name, color dot, and remaining/total weight
2026-03-17 12:40:38 +01:00
maziggy 7ab9b3e39f Fix mobile sidebar scroll, lint errors, and add tests for (#724)
- Fix mobile sidebar not scrollable when nav items exceed viewport
2026-03-17 12:31:11 +01:00
maziggy a6d307d739 Post work PR #693
Add tests, docs, and ruff fixes for per-user email notifications

  - Fix missing timezone import in email_service.py (F821)
  - Fix unused lambda arg in main.py asyncio done_callback (ARG005)
  - Fix E302 blank line spacing for mark_printer_stopped_by_user
  - Fix F821/UP037 forward reference in user_email_pref model
  - Fix SettingsPage test for duplicate "Notifications" text
  - Add backend unit tests for permissions, schemas, and templates
  - Add backend integration tests for user-notifications API
  - Add frontend tests for NotificationsPage
  - Add user_email_pref model import to test conftest
  - Update CHANGELOG and README
2026-03-17 12:24:36 +01:00
maziggy 446da087a0 Fix webhook notifications missing camera snapshot (#679)
Webhook providers did not include image data (e.g. camera snapshots
  from first layer complete notifications) even though other providers
  like Telegram, Pushover, and Discord already attached them. The webhook
  payload now includes a base64-encoded "image" field when a snapshot is
  available (generic format only, excluded from Slack format).
2026-03-16 15:10:39 +01:00
maziggy aa5df7a4ac Updated CHANGELOG.md 2026-03-16 13:30:24 +01:00
maziggy 63a905daf2 Bumped version 2026-03-16 12:46:25 +01:00
maziggy b889de91ba Allow spool assignment to empty AMS slots and fix profile label (#717)
Previously the "Assign Spool" button only appeared on configured slots,
  forcing users to manually configure first — redundant since assignment
  auto-configures the slot. Now shows on empty slots too. Also fixed the
  AMS hover card showing generic material type instead of the spool's
  slicer preset name after assignment.
2026-03-16 09:24:04 +01:00
maziggy fa6edfbcde Fix stored XSS vulnerabilities and unauthenticated auth toggle
- Sanitize project notes with DOMPurify before rendering via
    dangerouslySetInnerHTML (ProjectDetailPage.tsx)
  - Replace hand-rolled HTML sanitizer with DOMPurify in ProjectPageModal
    to prevent attribute injection via crafted 3MF href values
  - Block /api/v1/auth/setup when auth is already enabled to prevent
    unauthenticated clients from disabling authentication remotely
2026-03-15 15:31:49 +01:00
maziggy 0feed83ce4 Fix P2S camera TLS compatibility via OpenSSL proxy (#661)
The Debian ffmpeg package uses GnuTLS, whose hardened defaults reject
  TLS renegotiation and legacy ciphers that some Bambu printer firmwares
  (notably P2S) rely on — causing RTSP sessions to drop after a few
  seconds.

  Add a local TLS termination proxy (Python ssl/OpenSSL) that handles
  the TLS connection to the printer and exposes a plain RTSP port to
  ffmpeg. The proxy rewrites RTSP request-line URLs (rtsp://proxy →
  rtsps://printer) while preserving Authorization headers so Digest
  auth hashes remain valid.

  Also:
  - Reduce RTSP reconnect delay from 1.0s to 0.2s
  - Add ffmpeg fast-start flags (-probesize 32, -analyzeduration 0,
    -fflags nobuffer, -flags low_delay)
  - Fix external camera double rate-limiting causing choppy streams
  - Apply TLS proxy to external camera rtsps:// URLs and snapshot capture
  - Update orphan ffmpeg cleanup to match rtsp:// (proxied) URLs
  - Add unit tests for RTSP URL rewriting and proxy lifecycle
2026-03-15 11:52:32 +01:00
maziggy c5791e0b54 Fix spool assignment applying wrong filament profile (#681)
The Bambu Cloud API returns the base filament_id for versioned
  setting IDs (e.g. GFSL99 → GFL99 for all "Generic PLA" variants),
  so assigning a spool with a specific variant like "Generic PLA Silk"
  (GFSL99_01) would configure the AMS slot with the base "Generic PLA"
  profile (GFL99) instead of the correct one (GFL96).

  Added a post-resolution cross-check: if the resolved filament_id maps
  to a different name than the spool's stored preset name, reverse-lookup
  the correct filament_id from the built-in filament table.
2026-03-15 09:54:57 +01:00