Commit Graph
594 Commits
Author SHA1 Message Date
maziggy f6d760bb3e Add swipe-to-switch-printer and auto-navigate on tag scan
Swiping left/right on the SpoolBuddy touchscreen now cycles through
  online printers instead of triggering browser back/forward navigation.
  Uses touch-action: pan-y to suppress Chromium's native swipe history
  gesture. Auto-navigates to dashboard when a new NFC tag is detected
  on any other page, with edge detection so a persistent tag doesn't
  block manual navigation. Also wakes the screen if blanked.
2026-03-26 10:47:27 +01:00
maziggy ceb599ec00 Add swipe-to-switch-printer and auto-navigate on tag scan
Swiping left/right on the SpoolBuddy touchscreen now cycles through
  online printers instead of triggering browser navigation. Auto-navigates
  to dashboard when a new NFC tag is detected on any other page, with
  edge detection so a persistent tag doesn't block manual navigation.
2026-03-26 10:44:28 +01:00
maziggy 57a774c32f Auto-navigate SpoolBuddy to dashboard on tag scan
When an NFC tag is first detected while the UI is on a non-dashboard
  page, automatically navigate to the main dashboard. Uses edge detection
  (previous ref) so a persistently present tag doesn't block navigation
  to other pages. Also wakes the screen if the display was blanked.
2026-03-26 10:40:40 +01:00
maziggy 1c35ed94a5 Auto-navigate SpoolBuddy to dashboard on tag scan
When an NFC tag is detected while the UI is on a non-dashboard page
  (Settings, AMS, Write Tag, Calibration), automatically navigate back
  to the main dashboard to display the scanned spool. Also wakes the
  screen if the display blank timeout had kicked in.
2026-03-26 10:38:25 +01:00
maziggy c1676b1a32 The daemon now collects CPU temp, core count, load average, memory/disk
usage, OS info, and system uptime every heartbeat using stdlib-only reads
  from /proc and /sys. Stats are sent as a JSON blob in the heartbeat
  payload, stored in a new system_stats TEXT column, and displayed in a
  new "System" tab in SpoolBuddy Settings with color-coded usage bars.
2026-03-26 10:06:24 +01:00
maziggy 3c53d741a3 The daemon now collects CPU temp, core count, load average, memory/disk
usage, OS info, and system uptime every heartbeat using stdlib-only reads
  from /proc and /sys. Stats are sent as a JSON blob in the heartbeat
  payload, stored in a new system_stats TEXT column, and displayed in a
  new "System" tab in SpoolBuddy Settings with color-coded usage bars.
2026-03-26 10:03:46 +01:00
maziggy 4b14a4146c Add SpoolBuddy System tab with live OS stats from Raspberry Pi
The daemon now collects CPU temp, core count, load average, memory/disk
  usage, OS info, and system uptime every heartbeat using stdlib-only reads
  from /proc and /sys. Stats are sent as a JSON blob in the heartbeat
  payload, stored in a new system_stats TEXT column, and displayed in a
  new "System" tab in SpoolBuddy Settings with color-coded usage bars.
2026-03-26 09:59:58 +01:00
maziggy 77cb7158d2 Add SpoolBuddy System tab with live OS stats from Raspberry Pi
The daemon now collects CPU temp, core count, load average, memory/disk
  usage, OS info, and system uptime every heartbeat using stdlib-only reads
  from /proc and /sys. Stats are sent as a JSON blob in the heartbeat
  payload, stored in a new system_stats TEXT column, and displayed in a
  new "System" tab in SpoolBuddy Settings with color-coded usage bars.
2026-03-26 09:57:09 +01:00
maziggy 1df5130df2 Broadcast spool assignment changes via WebSocket for cross-tab updates
Assigning or unassigning a spool now broadcasts a spool_assignment_changed
  event to all connected WebSocket clients. The frontend handles this event
  by invalidating the spool-assignments and slotPresets caches, so other
  open tabs update automatically without a page reload.
2026-03-26 09:34:46 +01:00
maziggy 45892077ab Add material/profile mismatch warnings to SpoolBuddy Assign-to-AMS modal
The AssignToAmsModal was missing all material/profile validation guards
  that exist in the main AssignSpoolModal. Clicking an AMS slot now checks
  the spool's material and slicer profile against the target slot's current
  filament, showing a confirmation dialog on mismatch. Respects the global
  disable_filament_warnings setting. Uses existing i18n keys and ConfirmModal.
2026-03-26 09:23:42 +01:00
maziggy d749209ef4 Append /spool to Spoolman iframe URL in inventory page
When Spoolman is enabled, the sidebar filament item embedded
  Spoolman at its root URL. Now navigates to <url>/spool so users
  land directly on the spool management page.
2026-03-25 15:14:37 +01:00
maziggy c52ff1dcee Add Unassign button to edit spool modal
Allows removing a spool's AMS slot assignment directly from the
  edit modal, clearing the location column in the inventory table.
2026-03-25 14:14:40 +01:00
maziggy 91320e76d3 Clear all tag fields when deleting tag from spool
Delete Tag only cleared tag_uid, leaving tray_uuid, tag_type, and
  data_origin as stale data. Now sends all four fields as null.
2026-03-25 14:06:39 +01:00
maziggy c5dedff113 Show Assign or Unassign exclusively in SpoolBuddy slot picker
When a spool is already assigned/linked, only show Unassign/Unlink.
  When no spool is mapped, only show Assign/Link. Previously both
  buttons appeared simultaneously.
2026-03-25 13:58:47 +01:00
maziggy c822969df9 Add slot action picker to SpoolBuddy AMS page
Clicking an AMS slot now shows a picker with options: Configure AMS
  Slot, Assign Spool (inventory) or Link to Spoolman, and Unassign/
  Unlink when a mapping exists. Reuses the existing AssignSpoolModal
  and LinkSpoolModal components from the main Bambuddy frontend.
2026-03-25 13:53:24 +01:00
maziggy 504a0f9970 Compact SpoolBuddy settings Device tab to fit without scrolling
Remove branding/about card, fold Device ID into Device Info card,
  place Backend/Auth config and diagnostic buttons side by side in a
  2-column grid, remove redundant online/offline status from Device
  Info, and tighten spacing throughout.
2026-03-25 12:57:24 +01:00
maziggy 73aeee7bdf Compact SpoolBuddy settings Device tab to avoid scrolling
Remove the branding/about card, fold Device ID into the Device Info
  card, make diagnostic buttons a horizontal 3-column row, and put the
  API token input and Save button on the same line. Tighten spacing
  throughout so the tab fits on the small touchscreen without scrolling.
2026-03-25 12:52:43 +01:00
maziggy 88c0503009 Show spool notes as hover tooltip in Assign Spool modal (#793) 2026-03-25 08:55:06 +01:00
maziggy c9efa4b8bb Fix stale AMS slot data and empty slot button visibility (#784)
Some printers (e.g. H2D) only send {id, state} in incremental MQTT
  tray updates — no tray_type, tray_color, or other fields. When
  filament is unloaded (state changes from 11 to 10), the old tray
  data persisted indefinitely because the merge logic only updates
  fields present in the incoming message.

  Backend:
  - Detect tray state != 11 without tray_type in incremental updates
    and clear stale tray data (bambu_mqtt.py)
  - Expose tray `state` field via REST API and WebSocket broadcasts
    (printer.py schema, printers.py route, printer_manager.py)
  - Include AMS tray content in WebSocket dedup key so load/unload
    transitions trigger broadcasts (main.py)

  Frontend:
  - Add `state` to AMSTray interface (client.ts)
  - Show configure/assign buttons for state=10 (spool present, not
    loaded) but hide for state=9 (truly empty) on AMS/HT slots
  - Hide fill level bar on empty slots

  Tests:
  - 5 new tests covering state-based clearing, preservation, reload,
    and idempotency
2026-03-24 16:03:34 +01:00
maziggy 9f2722be36 Post work PR #763 2026-03-24 11:41:05 +01:00
maziggy 82278e8d93 Add external folder mounting for File Manager (#124)
Host directories (NAS, USB, network shares) can now be mounted
  into the File Manager without copying files. Files are indexed
  into the database on scan but read directly from their original
  location. Supports read-only mode, hidden file filtering, and
  automatic thumbnail extraction for 3MF/STL/gcode.

  - POST /library/folders/external — create with path validation
  - POST /library/folders/{id}/scan — discover/sync files
  - Block uploads, moves, and deletes for read-only external folders
  - Never delete actual files from external paths (DB-only removal)
  - Purple folder icon + info bar with rescan button in UI
  - i18n for all 7 languages
  - 19 backend + 11 frontend tests
2026-03-24 08:43:23 +01:00
maziggy 8be4bed384 Fix SpoolBuddy update UI responsiveness and stale data
Rewrote update button states: single `busy` flag stays set from click
  through to device pickup — no more gap with no feedback. Buttons hide
  while any operation is in progress. Listens for spoolbuddy-online
  WebSocket event to reload the page after daemon re-registers, ensuring
  fresh version and status. Set staleTime to 0 on update check queries.
2026-03-23 15:04:56 +01:00
maziggy 559d41cc5e Fix SpoolBuddy update UI: loading states, page reload, stale data
Check button had no visual feedback because isFetching doesn't trigger
  reliably with cached data — replaced with manual loading state. Removed
  kiosk restart via getty; the frontend now detects daemon re-registration
  via WebSocket and calls window.location.reload(), keeping the user on
  the same page and fetching all fresh data.
2026-03-23 14:59:12 +01:00
maziggy 1f24bd264a Fix SpoolBuddy update UI feedback and stale query cache
- Check button now shows spinner on refetch (isFetching vs isLoading)
  - Force Update button shows spinner while triggering
  - Reduced staleTime from 4 minutes to 30 seconds so the UI picks up
    version changes after an update without a long delay
2026-03-23 14:48:10 +01:00
maziggy 0e44e149bd ● Compact SpoolBuddy updates tab layout to fit without scrolling
Merged version, status, and update check into a single card. Buttons
  are side by side when up to date. Reduced padding and font sizes.
  Removed separate "complete" banner since status is now cleared on
  re-registration. SSH Setup section is smaller and more compact.
2026-03-23 14:36:58 +01:00
maziggy 811813165b Fix stale SpoolBuddy update status after daemon restart
After an SSH update completed, the UI kept showing "Update complete,
  daemon restarting..." and the old "update available" banner because
  nothing cleared the stale state. Registration now resets update_status
  when the daemon comes back, and WebSocket handlers for spoolbuddy_update
  and spoolbuddy_online invalidate the frontend queries immediately.
2026-03-23 13:55:12 +01:00
maziggy bc1bba078b Replace SpoolBuddy self-update with SSH-based updates from Bambuddy
The daemon's self-update mechanism (git fetch/reset on its own code) was
  fragile: .git permission errors, self-modifying code mid-run, hardcoded
  main branch. Bambuddy now SSHes into the SpoolBuddy Pi and drives the
  update remotely — matching its own branch, with step-by-step progress
  via WebSocket. Install script updated with SSH access, sudoers entry,
  and --ssh-pubkey flag for pairing.
2026-03-23 12:51:21 +01:00
maziggy 511ece791a Fix SpoolBuddy update check comparing against GitHub releases instead of backend version
The SpoolBuddy daemon update endpoint fetched GitHub releases and compared
  them against device.firmware_version, which always showed "up to date"
  because the comparison source was wrong. Now compares directly against
  APP_VERSION from the running backend, so a daemon at 0.2.3b1 correctly
  sees 0.2.3 as an available update.
2026-03-23 12:05:20 +01:00
maziggy 8e5625d1d9 Fix A1 virtual printer proxy by adding ports 2024-2026 (#757)
BambuStudio connects to undocumented proprietary ports 2024-2026
  on A1/P1S models during the print flow. The proxy wasn't forwarding
  these ports, causing connection refused (RST) and triggering the
  access code dialog instead of printing. MQTT and FTP worked fine —
  port 2024 was the sole blocker.

  Added transparent TCP pass-through proxies for ports 2024-2026,
  following the same pattern as the existing FileTransfer (6000) and
  RTSP (322) proxies. Silently ignored on models that don't use them.
2026-03-23 10:47:41 +01:00
maziggy 27e96c9827 Fix spool assignment on empty AMS slots (#784)
Remove "Assign Spool" and "Configure" buttons from empty AMS slot
  hover popups (standard AMS and HT AMS). Assigning a spool to a
  physically empty slot created a stuck state — no unassign button
  exists for empty slots, so the assignment couldn't be removed.
  External spool holders are unaffected.
2026-03-23 09:49:26 +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 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 d6e883652d Misc Spoolbuddy frontend fixes 2026-03-22 11:34:21 +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
Thomas Rambach 2cac7d0172 Feature: Admin Set Default Nav-Menu Order (#761)
Feature: Admin Set Default Nav-Menu Order (#761)
2026-03-21 09:30:18 +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 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 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 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 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 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 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 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