Commit Graph
1912 Commits
Author SHA1 Message Date
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 7d94bf7896 Fix P1S/P1P printer card showing "Printing" when idle (#813)
Some P1S/P1P firmware reports stg_cur=0 when idle, which maps to
  the "Printing" stage name and overrides the correct IDLE gcode_state
  on the printer card. Extend the existing A1/A1 Mini stg_cur idle bug
  workaround to also cover P1S and P1P models.
2026-03-25 17:55:36 +01:00
maziggy a36a0e09eb Fix daily beta release contributors list and add VP ports 2024-2026 to docker-compose
Strip @mentions from changelog text in docker-publish-daily-beta.sh
  so GitHub doesn't auto-generate a "Contributors" section in release
  notes. Add --generate-notes=false for extra safety. Also add ports
  2024-2026 (A1/P1S proprietary) to the docker-compose.yml bridge-mode
  port mapping and update the install script comment.
2026-03-25 16:47:27 +01:00
maziggy 6ac375a700 Fix stale MQTT connection not triggering reconnect (#813)
Two issues prevented recovery from stale printer MQTT connections:

  1. The spurious-disconnect filter (30s window) could suppress real
     keepalive-timeout disconnects (which fire at ~22.5s with keepalive=15s).
     Now checks rc.is_failure so error disconnects are never suppressed,
     and tightens the window from 30s to 10s.

  2. Stale detection (60s no messages) set state.connected=False but left
     the TCP socket open, so paho kept publishing into the void. Now
     force-closes the socket so paho's loop thread detects the break and
     auto-reconnects.
2026-03-25 16:16:50 +01:00
maziggy f74e860148 Removed start_bambuddy.bat 2026-03-25 15:43:41 +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 7c20efb7c3 Set _completion_triggered on unseen-RUNNING terminal states (#790)
When a printer enters FINISH/FAILED without Bambuddy ever seeing
  RUNNING (e.g. after a restart), mark _completion_triggered = True
  so the flag is clean for the next print cycle.
2026-03-25 14:34:53 +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 c1c31d8d91 Skip NTAG post-write verification — PN5180 read-back unreliable
The PN5180 cannot read more than 4 NTAG pages after a batch write:
  the second READ command (page 8+) returns rx_status=0 regardless of
  state machine reset strategy. The write itself succeeds (tag ACKs
  via SOF on every page). Remove verification and trust the writes.
2026-03-25 13:34:53 +01:00
maziggy a59c81d6a6 Fix NTAG read loop: IDLE→TRANSCEIVE once, set_transceive_mode after
Repeated IDLE→TRANSCEIVE resets inside the read loop broke the card
  session after the first READ (page 8 returned rx_status=0). Match
  the activate_type_a pattern: IDLE→TRANSCEIVE once before the loop,
  set_transceive_mode() for subsequent iterations.
2026-03-25 13:33:04 +01:00
maziggy 85ffb9e01f Fix NTAG read: apply same IDLE→TRANSCEIVE state machine reset
The verification read after writing failed because ntag_read_pages()
  used set_transceive_mode() which was a no-op when already in
  TRANSCEIVE. Apply the same IDLE→TRANSCEIVE reset pattern used in the
  write path, clear Crypto1, and add diagnostic logging.
2026-03-25 13:30:09 +01:00
maziggy 918dec4c19 Skip NTAG write ACK check — PN5180 can't capture 4-bit response
IRQ logging revealed the tag IS responding (RX_SOF_DET set) but the
  PN5180 cannot capture the 4-bit ACK as a complete frame — RX_IRQ
  never fires and RX_STATUS stays zero. Skip per-page ACK checking
  and rely on the read-back verification in ntag_write_pages().
2026-03-25 13:27:31 +01:00
maziggy 31ca2e7ddf Fix NTAG write: reset PN5180 state machine before WRITE command
The PN5180 transceive state machine wasn't being reset between the
  SELECT (from reactivate_card) and the WRITE command — just re-setting
  the TRANSCEIVE bits was a no-op. Use IDLE→TRANSCEIVE transition like
  activate_type_a does. Also clear Crypto1 bit and add IRQ status
  logging.
2026-03-25 13:24:57 +01:00
maziggy bae394d277 Add debug logging to NTAG write/verify path
Temporary diagnostics to identify which step of the NTAG write
  fails: per-page ACK status, reactivation, read-back, or data
  mismatch. Enable DEBUG level for pn5180 module.
2026-03-25 13:21:27 +01:00
maziggy 72536c93a0 Fix NTAG write ACK detection for 4-bit response
The NTAG WRITE ACK is 4 bits (0x0A), not a full byte. The PN5180
  RX_STATUS register reports 0 complete bytes with 4 extra bits, but
  the check only looked at the byte count — returning False on every
  successful write. Check both byte and bit fields of RX_STATUS.
  Also bump post-write delay from 5ms to 10ms for margin.
2026-03-25 13:18:41 +01:00
maziggy f4d8e1ecd3 Fix SpoolBuddy NFC write failing on NTAG 213/215/216 tags
Three issues:

  1. SAK gate too strict — NTAG chips can report SAK 0x04 (MIFARE
     Ultralight family) instead of 0x00. Accept both in nfc_reader.py
     and main.py.

  2. TX CRC disabled for NTAG WRITE — the NTAG spec requires CRC on
     the WRITE command frame. Enable TX CRC in ntag_write_page().

  3. TX CRC disabled for NTAG READ — the post-write verification read
     also failed because ntag_read_pages() sent the READ command
     without CRC. Enable TX CRC there too.
2026-03-25 13:15:45 +01:00
maziggy 9d4f57d54d Fix SpoolBuddy NFC write failing on NTAG 213/215/216 tags
Two issues:

  1. SAK gate too strict — NTAG chips can report SAK 0x04 (MIFARE
     Ultralight family) instead of 0x00. Accept both in nfc_reader.py
     and main.py.

  2. TX CRC disabled during WRITE — the NTAG WRITE command (0xA2)
     requires a CRC on the frame. The PN5180 was sending without CRC,
     causing the tag to NAK every write. Enable TX CRC for writes
     (RX CRC stays off for the 4-bit ACK).
2026-03-25 13:12:57 +01:00
maziggy f71367bb4e Fix SpoolBuddy NFC write rejecting NTAG 215 tags with SAK=0x04
NTAG 213/215/216 chips can report SAK 0x04 (MIFARE Ultralight family)
  instead of 0x00 during anticollision. Accept both values for NTAG
  detection and write operations in nfc_reader.py and main.py.
2026-03-25 13:10:11 +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 3c1fdd13b9 Added back debug logs to Spoolbuddy test scripts 2026-03-25 12:16:49 +01:00
maziggy d5c520dd71 Added back debug logs to Spoolbuddy test scripts 2026-03-25 12:15:29 +01:00
maziggy 74387b7c38 Added back debug logs to Spoolbuddy test scripts 2026-03-25 12:15:22 +01:00
maziggy f96d211612 Added back debug logs to Spoolbuddy test scripts 2026-03-25 12:13:31 +01:00
maziggy 2b1fe03159 Fix SpoolBuddy scale first reading and extract hardware drivers
The NAU7802 ADC returns a stale max-scale value (0x7FFFFF) on its
  first conversion after power-up, polluting the moving average and
  making the initial weight report wildly inaccurate. Flush the first
  reading during init().

  Also extract both hardware drivers out of diagnostic scripts into
  proper daemon modules:
  - NAU7802 scale driver: scripts/scale_diag.py -> daemon/nau7802.py
  - PN5180 NFC driver: scripts/read_tag.py -> daemon/pn5180.py

  The production daemon was importing driver classes from test scripts
  since the original SpoolBuddy commit. Diagnostic scripts now import
  from the driver modules. Removed the sys.path hack from main.py.
2026-03-25 11:57:28 +01:00
maziggy 5926e722f8 Fix H2D external spool print failing with 0700_8012 (#797)
BambuStudio converts virtual tray IDs (254/255) to -1 in the flat
  ams_mapping and relies on ams_mapping2 for external spool routing.
  Bambuddy was passing raw 254/255 in the flat array, which H2D firmware
  rejects with "Failed to get AMS mapping table".

  - Convert external tray IDs to -1 in flat ams_mapping (match BambuStudio)
  - Fix ams_mapping2 for external trays: each virtual tray is its own AMS
    unit with slot_id 0, not a shared unit differentiated by slot
  - Fix main/deputy nozzle ID comment (255=main, 254=deputy per BambuStudio)
  - Add 8 unit tests for start_print() mapping construction
2026-03-25 11:38:27 +01:00
maziggy a5ea3f599a Minor Spoolbuddy install.sh fixes 2026-03-25 10:24:47 +01:00
maziggy f96b9ded56 Add WiFi safeguard and apt upgrade to SpoolBuddy install script
Install script now runs apt-get upgrade -y after installing system
  packages. A WiFi safeguard (APT hook + helper script) is installed
  first, backing up NetworkManager connections before dpkg and restoring
  them if wiped — prevents headless Pis from losing WiFi during upgrades.
2026-03-25 10:22:22 +01:00
maziggy cb31a6cd33 Add apt upgrade to SpoolBuddy install script
Runs apt-get upgrade -y after installing system packages and the WiFi
  safeguard hook. Ensures the Pi is fully up to date before deploying
  SpoolBuddy, and the WiFi safeguard protects NM connections during
  the upgrade.
2026-03-25 10:14:16 +01:00
maziggy 53da037048 Add WiFi safeguard to SpoolBuddy install script
APT hook backs up NetworkManager WiFi connections before dpkg runs
  and restores them if they get wiped. Prevents headless SpoolBuddy
  Pis from losing WiFi after apt upgrade (observed with Bookworm
  kernel/raspi-config updates clearing system-connections/).
2026-03-25 09:53:14 +01:00
maziggy 88c0503009 Show spool notes as hover tooltip in Assign Spool modal (#793) 2026-03-25 08:55:06 +01:00
maziggy b8fa2df36d Increase database connection pool limits for large printer farms
QueuePool exhaustion at 100+ printers. Bumped pool_size 10→20,
  max_overflow 20→200, and SQLite busy_timeout 5s→15s.
2026-03-25 08:20:22 +01:00
maziggy 95c703282d Fix missing image thumbnails in external folder scan (#124)
External folder scan generated thumbnails for 3mf/stl/gcode files but
  skipped image files. Added IMAGE_EXTENSIONS check with
  create_image_thumbnail() to the scan loop.
2026-03-24 16:32:45 +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
Keybored 6e648804fc [Feature] Spoolbuddy Fixes and Improvements (#787)
[Feature] Spoolbuddy Fixes and Improvements (#787)
2026-03-24 11:56:33 +01:00
maziggy 9f2722be36 Post work PR #763 2026-03-24 11:41:05 +01:00
Keybored 3f7d0e2d55 Add notification for no spool assigned for active trays, improve usage tracker logic in edge cases (#789)
Add notification for no spool assigned for active trays, improve usage tracker logic in edge cases (#789)
2026-03-24 11:31:32 +01:00
maziggy dd75c8f0c9 feat: auto-link untagged inventory spools on AMS insert (#538)
When a Bambu Lab spool is detected in the AMS but no tag match exists,
  check for an untagged inventory spool with matching material/subtype/color
  before creating a new entry. Links the RFID tag to the existing spool
  (data_origin="rfid_linked") to prevent duplicate inventory entries.
2026-03-24 09:23:25 +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 293ebd9b3f Fix ffmpeg process leak causing multi-GB memory growth (#776)
When a user closed the camera viewer, the stop endpoint killed the
  ffmpeg process but never signaled the stream generator's disconnect
  event. The generator saw "process died" as a dropped RTSP session
  and respawned ffmpeg — up to 30 times per stream. The orphan cleanup
  couldn't catch these because they were still tracked as active.

  - Add per-stream disconnect events dict so stop endpoint can signal
    generators to stop reconnecting before killing the process
  - Check if stream_id was removed from _active_streams before
    reconnecting (belt-and-suspenders with the event)
  - Track frame timestamps per stream_id instead of per printer_id
    so stale detection isn't fooled by newer streams for the same
    printer
  - Reduce stale thresholds from 120s+60s to 60s+30s
  - Signal disconnect events from cleanup when killing stale streams
2026-03-24 07:49:54 +01:00
maziggy d833cb88ff Updated CHANGELOG 2026-03-23 16:24:08 +01:00
maziggy 7b91cde6db Fixed typo in version 2026-03-23 16:14:44 +01:00
maziggy 745ff232eb Fix log flood: "State is FINISH but completion NOT triggered" (#790)
Diagnostic log added in 0.2.2.1 fired on every MQTT update while a
  printer was in FINISH/FAILED state, not just on the state transition.
  For farms with multiple idle printers, this produced thousands of log
  lines per minute. Guard the log to only fire once when the state first
  changes to FINISH/FAILED.
2026-03-23 16:07:44 +01:00
maziggy b8a3aa842b Add tests for SpoolBuddy SSH update service and settings UI
15 backend unit tests covering keypair management, branch detection,
  SSH command execution (success/failure/timeout), and full update flow
  with error handling. 4 new frontend tests for the Updates tab (version
  display, buttons, SSH setup, update available state).
2026-03-23 15:55:44 +01:00
maziggy c42d834219 Revert "version test"
This reverts commit cf8f43169b.
2026-03-23 15:46:10 +01:00