New splash shows only the SpoolBuddy logo with green glow bloom,
radial gradient, light rays, and vignette. Removed Bambuddy branding.
Includes generator script for easy customization.
Defers initramfs rebuild during install until after Plymouth theme
is configured, avoiding redundant rebuilds from apt hooks.
New splash shows only the SpoolBuddy logo with green glow bloom,
radial gradient, light rays, and vignette. Removed Bambuddy branding.
Includes generator script for easy customization.
Defers initramfs rebuild during install until after Plymouth theme
is configured, avoiding redundant rebuilds from apt hooks.
Reverts the fim/fbi experiment — Plymouth is the only splash tool
that reliably handles Pi KMS/DRM from early boot. install.sh is
restored to the original Plymouth setup. The new polished splash
image and generator script are kept.
New splash shows only the SpoolBuddy logo with baked-in green glow,
radial gradient background, subtle light rays, and vignette effects
(66KB vs 205KB). Removed Bambuddy branding. Includes generator
script for easy customization.
Plymouth ran as a persistent daemon throughout boot, consuming memory
and competing for framebuffer allocation. fim renders via DRM (Pi KMS
doesn't expose a usable legacy framebuffer), displays the image, and
exits — zero ongoing resource cost.
New splash image shows only the SpoolBuddy logo with baked-in glow,
radial gradient, light rays, and vignette effects (66KB vs 205KB).
Install script auto-purges Plymouth on existing installs in a single
pass to avoid redundant initramfs rebuilds.
Plymouth ran as a persistent daemon throughout boot, consuming memory
and competing for framebuffer allocation. fbi writes pixels directly
to the framebuffer and exits — zero ongoing resource cost.
New splash image shows only the SpoolBuddy logo with baked-in glow,
radial gradient, light rays, and vignette effects (66KB vs 205KB).
Install script auto-purges Plymouth on existing installs in a single
pass to avoid redundant initramfs rebuilds.
Plymouth ran as a persistent daemon throughout boot, consuming memory
and competing for framebuffer allocation. fbi writes pixels directly
to the framebuffer and exits — zero ongoing resource cost.
New splash image shows only the SpoolBuddy logo with baked-in glow,
radial gradient, light rays, and vignette effects (66KB vs 205KB).
Install script auto-removes Plymouth on existing installs.
Narrowed CSS selector to only target max-w-2xl modals (Assign Spool)
not max-w-sm ones (slot action picker). Removed inner max-h-96 on
the spool grid to eliminate nested scrollbars.
CSS rules scoped via data-spoolbuddy-kiosk force the modal panel to
90vh with flex column layout. Content area scrolls, header/footer
pinned. Uses height (not just max-height) so flex-basis auto works
correctly. No flash — CSS applies before paint.
useEffect in SpoolBuddyAmsPage applies inline styles to the modal
panel after render (requestAnimationFrame + setTimeout) to cap it
at 90vh with scrollable content. Targets the DOM directly to avoid
CSS specificity issues with Tailwind v4.
Used a ref callback wrapper in SpoolBuddyAmsPage to directly apply
inline styles (max-height 90vh, flex column, scrollable content) to
the shared AssignSpoolModal DOM elements without modifying the
shared component.
Added data-spoolbuddy-kiosk attribute to the SpoolBuddy layout and
global CSS rules that cap modals at 90vh with scrollable content on
the small touchscreen, without modifying shared components.
Added scoped CSS in SpoolBuddyAmsPage that constrains the shared
AssignSpoolModal to 90vh with scrollable content and pinned
header/footer, without modifying the shared component.
Added scoped CSS in SpoolBuddyAmsPage that constrains the shared
AssignSpoolModal to 90vh with scrollable content, without modifying
the shared component used by the main Bambuddy frontend.
The NFC Diag and Scale Diag buttons on the Write Tag page's right
card were misplaced — diagnostics are already available on the
Settings page. Removed the buttons and all associated dead code.
When the virtual keyboard opened on the SpoolBuddy device tab, the
API token field and Save button were hidden behind the keyboard.
The keyboard now adds bottom scroll padding and scrolls the parent
card (not just the focused input) to the top of the visible area,
keeping all related fields accessible.
When the virtual keyboard opened on the SpoolBuddy device tab, the
Backend URL and API Token fields were hidden behind the keyboard
overlay. The keyboard now adds temporary bottom padding to the
scrollable container so inputs scroll above it, and removes the
padding on dismiss.
Non-passive touchmove listener with preventDefault() blocks Chromium's
compositor-level back/forward swipe gesture. Once horizontal movement
is detected, the gesture is locked and all further touchmove events
are prevented for that swipe. Removed touch-action: pan-y which was
insufficient on its own.
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.
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.
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.
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.
The read_tag.py diagnostic script had stale PN5180 NTAG methods: TX CRC
was off (should be on), no Crypto1 clear, no IDLE→TRANSCEIVE state
reset. Multi-batch reads failed because the PN5180 enters an
unrecoverable state after an NTAG READ — requires a full GPIO hardware
reset between 4-page batches. Also rejected SAK 0x04 as unsupported,
and failed hard when reading past the end of smaller tags (MIFARE
Ultralight has 16 pages vs NTAG's 44+). Synced write methods with
daemon.
The read_tag.py diagnostic script had stale PN5180 NTAG methods: TX CRC
was off (should be on), no Crypto1 clear, no IDLE→TRANSCEIVE state
reset. Multi-batch reads failed because the PN5180 enters an
unrecoverable state after an NTAG READ — requires a full GPIO hardware
reset between 4-page batches. Also rejected SAK 0x04 as unsupported.
Synced write methods with daemon.
The read_tag.py diagnostic script had stale PN5180 NTAG methods: TX CRC
was off (should be on), no Crypto1 clear, no IDLE→TRANSCEIVE state
reset, and multi-batch reads failed because the PN5180 can't issue
consecutive NTAG READs without a full RF power cycle. Added extended-
timing reactivation (50ms gaps vs 10ms) between 4-page batches. Also
rejected SAK 0x04 as unsupported. Synced write methods with daemon.
The read_tag.py diagnostic script had stale PN5180 NTAG methods: TX CRC
was off (should be on), no Crypto1 clear, no IDLE→TRANSCEIVE state
reset, and multi-batch reads failed because subsequent READ commands
need a full state machine reset between batches. Also rejected SAK 0x04
as unsupported. Synced register setup and write methods with daemon.
The read_tag.py diagnostic script had stale PN5180 NTAG methods: TX CRC
was off (should be on), no Crypto1 clear, no IDLE→TRANSCEIVE state
reset, and the PN5180 drops the card after each READ batch requiring
reactivation between 4-page reads. Also rejected SAK 0x04 as
unsupported. Synced register setup with daemon and added per-batch
card reactivation.
The read_tag.py diagnostic script had stale PN5180 NTAG methods that
were never synced with the daemon's fixes: TX CRC was off (should be
on), no Crypto1 clear, no IDLE→TRANSCEIVE state reset, and unreliable
ACK/verification logic. Also rejected SAK 0x04 as unsupported. Synced
ntag_read_pages, ntag_write_page, and ntag_write_pages with daemon.
The read_tag.py diagnostic script only accepted SAK 0x00 for NTAG,
showing "Unsupported tag type" for chips reporting SAK 0x04 (MIFARE
Ultralight family). The daemon already handled both values — the
diagnostic was missed. Now accepts both 0x00 and 0x04.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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().