Commit Graph
104 Commits
Author SHA1 Message Date
maziggy 464d56ea0d fix(install): make SpoolBuddy kiosk usable on first boot in full-mode install
Full-mode install booted into an unusable kiosk:
  - Chromium opened before uvicorn → "can't connect to localhost"
  - After reload, requires_setup=true hijacked /spoolbuddy → /setup
  - Touch-only Pi has no keyboard to complete the setup wizard
  - Declining auth left the user at / instead of the kiosk

  Fixes, bundled:

  1. backend/app/cli.py kiosk-bootstrap now, in one DB transaction:
     - creates a scoped API key (can_read_status=True, rest false)
     - upserts setup_completed=true
     so AuthContext never redirects and the kiosk URL loads directly. Users
     who want auth can still enable it from the admin UI; the provisioned
     key keeps working.

  2. install.sh full-mode runs the CLI as the bambuddy service user after
     create_bambuddy_service and sed-replaces the CHANGE_ME_AFTER_SETUP
     placeholder in spoolbuddy/.env.

  3. The generated spoolbuddy-kiosk-launch polls ${backend_url}/health for
     up to 60s before exec'ing chromium, so cold boots wait for uvicorn
     instead of flashing ERR_CONNECTION_REFUSED.

  Standalone mode was unaffected — users supply a real key from their
  existing Bambuddy before install.
2026-04-18 08:14:53 +02:00
maziggy 3502ab33c5 fix(install): auto-provision SpoolBuddy kiosk API key in full-mode install
Full-mode install wrote CHANGE_ME_AFTER_SETUP as SPOOLBUDDY_API_KEY because
  no admin exists yet to create a real one. On reboot the kiosk launched with
  that placeholder, AuthContext rejected it, and the user hit the Bambuddy
  login page instead of the kiosk. Standalone mode was unaffected — users
  paste a real key from their existing Bambuddy before install.

  Adds backend/app/cli.py with a kiosk-bootstrap subcommand that creates a
  scoped APIKey row directly in the DB (can_read_status=True, everything else
  false) and prints the full key to stdout. install.sh full-mode runs it as
  the bambuddy service user after create_bambuddy_service, captures the key,
  and sed-replaces the placeholder in spoolbuddy/.env. Idempotent with
  --force for re-installs.

  Drops the outdated "create an API key and edit .env" next-step block since
  the kiosk is now provisioned automatically.
2026-04-18 07:40:38 +02:00
maziggy 9e4cae82b9 . 2026-04-12 11:16:43 +02:00
maziggy 749257e97a . 2026-04-12 11:12:05 +02:00
maziggy a25f200529 . 2026-04-12 11:09:59 +02:00
maziggy 13d759c7ed . 2026-04-12 11:08:26 +02:00
maziggy 969174cc81 . 2026-04-12 11:05:22 +02:00
maziggy 2d6ddc431b feat(spoolbuddy): auto-wake display on NFC tag scan or scale activity (#945)
Display now powers on via wlopm when the daemon detects an NFC tag or
  a significant weight change (>=50g, i.e. spool placed/removed) while
  the screen is blanked.  Minor scale fluctuations no longer wake the
  display or prevent blanking.  The daemon only re-blanks screens it woke
  itself — touch-based wake/blank stays with swayidle so the two don't
  conflict.  Daemon discovers the Wayland session from the shared runtime
  dir since it runs as a systemd service outside the compositor.
2026-04-12 10:56:44 +02:00
maziggy 25203b3491 feat(spoolbuddy): auto-wake display on NFC tag scan or scale activity (#945)
Display now powers on via wlopm when the daemon detects an NFC tag or
  a significant weight change (>=50g, i.e. spool placed/removed) while
  the screen is blanked.  Minor scale fluctuations no longer wake the
  display or prevent blanking.  The daemon only re-blanks screens it woke
  itself — touch-based wake/blank stays with swayidle so the two don't
  conflict.  Daemon discovers the Wayland session from the shared runtime
  dir since it runs as a systemd service outside the compositor.
2026-04-12 10:51:11 +02:00
maziggy f135605908 feat(spoolbuddy): auto-wake display on NFC tag scan or scale activity (#945)
Display now powers on via wlopm when the daemon detects an NFC tag or
  weight change while the screen is blanked.  The daemon only re-blanks
  screens it woke itself — touch-based wake/blank stays with swayidle so
  the two don't conflict.  Daemon discovers the Wayland session from the
  shared runtime dir since it runs as a systemd service outside the
  compositor.
2026-04-12 10:47:04 +02:00
maziggy ca1b0a2cd5 feat(spoolbuddy): auto-wake display on NFC tag scan or scale activity (#945)
Display now powers on via wlopm when the daemon detects an NFC tag or
  weight change while the screen is blanked.  Daemon discovers the Wayland
  session from the shared runtime dir and coexists with swayidle which
  continues to handle touch-based wake independently.
2026-04-12 10:41:57 +02:00
maziggy d42250cb68 fix(spoolbuddy): add idle-watchdog diagnostics and Wayland autodetect (#937)
Follow-up to the SpoolBuddy LCD power-off fix. Field-testing on a
  Raspberry Pi OS Bookworm kiosk showed the watchdog appearing absent
  from `ps ax | grep spool` — actually it had already `exec`'d into
  `swayidle`, but with no logging there was no way to confirm that
  without manually re-running the script.

  - spoolbuddy-idle.sh now redirects stdout+stderr to
    ~/.cache/spoolbuddy-idle.log and prints WAYLAND_DISPLAY,
    XDG_RUNTIME_DIR, PATH, the resolved timeout, and the final
    `swayidle` command line on every start.
  - Auto-detect WAYLAND_DISPLAY by scanning $XDG_RUNTIME_DIR for a
    wayland-* socket (10s retry loop) so the script survives the race
    where labwc launches autostart before exporting its env.
  - Default XDG_RUNTIME_DIR to /run/user/$(id -u) if unset.
2026-04-11 13:02:38 +02:00
maziggy c4ebe5a70c ● fix(spoolbuddy): actually power off HDMI on idle instead of CSS overlay (#937)
The SpoolBuddy kiosk's "screen blank timeout" setting only painted a
  black CSS overlay over the browser window — the HDMI panel's backlight
  stayed on indefinitely, wasting power and risking burn-in on
  OLED/LED panels.

  Move blanking down to the OS layer:

  - install.sh now installs swayidle + wlopm + jq and rewrites labwc's
    autostart to launch a new spoolbuddy-idle.sh watchdog instead of the
    old `wlr-randr --on` keep-alive loop.
  - The watchdog sources /opt/bambuddy/spoolbuddy/.env, derives device_id
    from the first non-loopback MAC (same algorithm as daemon/config.py),
    fetches the configured blank_timeout from the backend once on boot,
    and execs `swayidle -w timeout $T 'wlopm --off HDMI-A-1' resume
    'wlopm --on HDMI-A-1'`. Touch/keypress wakes via labwc's input event
    path. timeout=0 skips swayidle entirely so existing installs that
    never picked a timeout keep their current always-on behavior.
  - New GET /api/v1/spoolbuddy/devices/{id}/display endpoint returns the
    current brightness + blank_timeout. Gated on INVENTORY_UPDATE (same
    level the daemon heartbeat key already uses) so existing SpoolBuddy
    API keys work without extra permissions.
  - SpoolBuddyLayout drops blanked state, the blank timer, activity
    listeners, resetActivity, and the CSS overlay. Runtime updates to
    the timeout take effect on next kiosk/browser restart; default for
    newly-enabled blanking is 300 seconds.
2026-04-11 12:42:49 +02:00
maziggy b76d6210cf Add SpoolBuddy quick menu with power control and system commands (#893)
Swipe down from the top of the SpoolBuddy display to open a quick-access
  menu for toggling printer smart plugs and managing the device (restart
  daemon, restart browser, reboot, shutdown). All destructive actions
  require confirmation.

  Backend: new POST /spoolbuddy/devices/{id}/system/command endpoint
  queuing reboot/shutdown/restart_daemon/restart_browser commands.
  Daemon: handles commands via subprocess (sudo reboot, systemctl restart).
  Frontend: SpoolBuddyQuickMenu component, swipe-down gesture detection,
  i18n keys for all 7 locales.
2026-04-08 11:29:44 +02:00
maziggy 42028ffc98 Fix SpoolBuddy kiosk screen blanking immediately on boot
The touchscreen display blanked right after boot, requiring a touch
  to wake. Two issues: no consoleblank=0 in cmdline.txt (kernel blanks
  the console during Plymouth→labwc transition), and the wlr-randr
  anti-blank loop slept 60s before its first run.

  - Add consoleblank=0 to kernel cmdline in install.sh
  - Move sleep after wlr-randr in labwc autostart so it fires immediately
2026-04-04 10:45:55 +02:00
maziggy a4b927f2d2 Fix SpoolBuddy add-to-inventory, dashboard crash, and kiosk display issues
- Round scale weight to integer before sending to backend (Pydantic
    rejects non-whole floats for int fields), move modal close to finally
    block, add error toast with actual API message
  - Fix null-field crash in SpoolInfoCard prop construction: pick one
    source object instead of per-field ?? fallbacks that crash when
    displayedSpool has null subtype/brand/rgba and matchedSpool is null
  - Add React ErrorBoundary to App so crashes show error instead of
    black screen
  - Remove --max-old-space-size=128 and --enable-low-end-device-mode
    from kiosk Chromium flags (crashed renderer/display)
  - Append kiosk flags to Pi GPU defaults instead of resetting them
  - Add wlr-randr keep-alive and screenBlankTimeout=0 to prevent
    display blanking on labwc 0.9.x
  - Fix tests: add ToastProvider to Dashboard test wrapper, update
    StatusBar tests for removed animate-pulse class
2026-03-28 10:51:51 +01:00
maziggy 09ebac1c09 Reduce SpoolBuddy kiosk idle CPU load from ~3.3 to ~0.9
Frontend: replace expensive idle dashboard animations (3x animate-ping
  with scale transforms, blur-2xl glow, continuous animate-pulse on
  status dots) with static NFC rings and slow 5s color-cycling spool.
  Chromium: add --disable-extensions, --disable-background-timer-throttling,
  --memory-pressure-off, --disable-renderer-backgrounding, --disable-breakpad,
  and --js-flags=--max-old-space-size=128. Install script: mask stripped
  services (not just disable) to prevent socket/dbus reactivation; use
  /etc/systemd/user/ global overrides for user services instead of
  unreliable su-based systemctl --user. Remove chromium/upower from
  strip_packages since kiosk reinstalls them immediately.
2026-03-27 14:04:11 +01:00
maziggy 5fe4134d86 Reduce SpoolBuddy kiosk CPU/memory pressure
Add Chromium flags to cut overhead on Pi: disable extensions, crash
  reporter, background timer throttling, renderer backgrounding, and cap
  V8 heap at 128MB. Mask (not just disable) stripped system services to
  prevent socket/dbus reactivation, and add xdg-permission-store to the
  disable list. Remove chromium and upower from strip_packages since the
  kiosk needs them — they were being uninstalled then immediately
  reinstalled on every run.
2026-03-27 13:32:49 +01:00
maziggy 70382ec55c Add Chromium flags to cut overhead on Pi: disable extensions, crash
reporter, background timer throttling, renderer backgrounding, and cap
  V8 heap at 128MB. Also mask (not just disable) stripped system services
  to prevent socket/dbus reactivation, and add xdg-permission-store to
  the disable list.
2026-03-27 13:28:12 +01:00
maziggy 7a0ea8faed Revert " Optimize SpoolBuddy kiosk performance on Raspberry Pi"
This reverts commit 24cda842af.
2026-03-27 12:00:14 +01:00
maziggy a8b50e809f Optimize SpoolBuddy kiosk performance on Raspberry Pi 2026-03-27 11:45:28 +01:00
maziggy 24cda842af Optimize SpoolBuddy kiosk performance on Raspberry Pi
Replace Chromium with cog (WPE WebKit) for the kiosk browser. Cog is
  purpose-built for embedded kiosk displays with a fraction of Chromium's
  CPU and memory footprint on Pi hardware.

  Add React Query `select` to SpoolBuddyLayout and SpoolBuddyDashboard
  printer status queries so only `connected` is extracted. Temperature,
  fan, and progress changes no longer trigger re-renders on every MQTT
  tick.

  Expand service/package stripping to disable pipewire audio stack, CUPS
  printing, rpcbind, upower, polkit, accounts-daemon, xdg-desktop-portal,
  and mpris-proxy. Add user-level service masking for pipewire/portals.

  Update SSH update cache clearing to handle both WPE WebKit and legacy
  Chromium cache paths.
2026-03-27 11:43:55 +01:00
maziggy 54c67f9e4e Optimize SpoolBuddy kiosk performance on Raspberry Pi
Override Debian's default Chromium flags via /etc/chromium.d/spoolbuddy-kiosk
  to disable GPU rasterization, enable low-end device mode, and disable smooth
  scrolling/background networking. The system default --enable-gpu-rasterization
  conflicted with per-launch flags — the new config replaces all system defaults
  so kiosk flags take effect cleanly.

  Expand service/package stripping to disable pipewire audio stack, CUPS
  printing, rpcbind, upower, polkit, accounts-daemon, xdg-desktop-portal,
  and mpris-proxy. Add user-level service masking for pipewire/portals
  that system-level disable misses.
2026-03-27 10:44:58 +01:00
maziggy 26c2549a56 Optimize SpoolBuddy kiosk performance on Raspberry Pi
Add Chromium performance flags (disable-gpu-rasterization,
  enable-low-end-device-mode, disable-smooth-scrolling,
  disable-background-networking, disable-dev-shm-usage) to reduce
  CPU load from ~54% to manageable levels on Pi 4B.

  Expand service/package stripping to disable pipewire audio stack,
  CUPS printing, rpcbind, upower, polkit, accounts-daemon,
  xdg-desktop-portal, and mpris-proxy. Add user-level service
  masking for pipewire/portals that system-level disable misses.
2026-03-27 10:26:56 +01:00
Keybored eb3450b1d0 Spoolbuddy init and diagnostic improvements (#814)
Spoolbuddy init and diagnostic improvements (#814)
2026-03-26 16:16:09 +01:00
maziggy e4999f48fb Polish SpoolBuddy boot splash and reduce initramfs rebuilds
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.
2026-03-26 13:05:20 +01:00
maziggy 12c2b57962 Polish SpoolBuddy boot splash and reduce initramfs rebuilds
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.
2026-03-26 13:00:06 +01:00
maziggy b1f2670058 Revert install.sh to Plymouth, keep polished splash
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.
2026-03-26 12:52:14 +01:00
maziggy 58b5e3ae09 Replace Plymouth with fim for SpoolBuddy boot splash
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.
2026-03-26 12:22:29 +01:00
maziggy 387aafaee4 Replace Plymouth with fbi for SpoolBuddy boot splash
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.
2026-03-26 12:10:42 +01:00
maziggy 4c7141f738 Replace Plymouth with fbi for SpoolBuddy boot splash
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.
2026-03-26 12:03:49 +01:00
maziggy 4521366a5b Fix Read Tag diagnostic failing on NTAG tags
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.
2026-03-26 10:32:44 +01:00
maziggy d341b86748 Fix Read Tag diagnostic failing on NTAG tags
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.
2026-03-26 10:31:18 +01:00
maziggy cd92d0099e Fix Read Tag diagnostic failing on NTAG tags
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.
2026-03-26 10:28:25 +01:00
maziggy 0aeee26b3e Fix Read Tag diagnostic failing on NTAG tags
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.
2026-03-26 10:25:41 +01:00
maziggy a321a709b5 Fix Read Tag diagnostic failing on NTAG tags
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.
2026-03-26 10:23:07 +01:00
maziggy 1c96b00a6b Fix Read Tag diagnostic failing on NTAG tags
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.
2026-03-26 10:17:17 +01:00
maziggy e237d3ba28 Fix Read Tag diagnostic rejecting SAK 0x04 NTAG tags
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.
2026-03-26 10:12:09 +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 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 3c1fdd13b9 Added back debug logs to Spoolbuddy test scripts 2026-03-25 12:16:49 +01:00