Просмотр исходного кода

Add SpoolBuddy tag detection modal and fix NFC reader polling

  Frontend: Replace inline SpoolInfoCard/UnknownTagCard with full-screen
  TagDetectedModal that auto-opens on NFC tag detection. Known spools show
  remaining weight, fill bar, and offer "Assign to AMS" (new sub-modal with
  printer selector + AMS slot grid) and "Sync Weight". Unknown tags offer
  "Add to Inventory" and "Link to Spool". Modal stays open on tag removal,
  won't re-open for dismissed tags, reopens on re-place after removal.

  Daemon: Fix PN5180 NFC reader failing to maintain tag detection. After a
  successful SELECT the card stays in ACTIVE state and ignores subsequent
  WUPA/REQA, causing immediate false "tag removed" events. Added a brief
  RF off/on cycle (13ms) before each poll to force cards back to IDLE
  state. Also added a preventive full hardware reset every 60s when idle
  to recover from deeper stuck states where activate_type_a() silently
  returns None without exceptions. Heartbeat now reports actual nfc_ok/
  scale_ok instead of hardcoded True.
maziggy 2 месяцев назад
Родитель
Сommit
2d814ea5f4
2 измененных файлов с 13 добавлено и 1 удалено
  1. 1 1
      CHANGELOG.md
  2. 12 0
      spoolbuddy/daemon/nfc_reader.py

+ 1 - 1
CHANGELOG.md

@@ -17,7 +17,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **Windows Install Fails With "Syntax of the Command Is Incorrect"** ([#544](https://github.com/maziggy/bambuddy/issues/544)) — The `start_bambuddy.bat` launcher had Unix (LF) line endings instead of Windows (CRLF). When a user's git config has `core.autocrlf=false` or `input`, the file is checked out with LF endings and `cmd.exe` cannot parse it. Added a `.gitattributes` file that forces CRLF for all `.bat` files regardless of git config.
 - **Queue Badge Shows on Incompatible Printers** ([#486](https://github.com/maziggy/bambuddy/issues/486)) — The purple queue counter badge in the printer card header showed on all printers of the same model when a job was scheduled for "any [model]", even if the printer didn't have the matching filament color loaded. The `PrinterQueueWidget` (which shows "Clear Plate & Start") already filtered by filament type and color, but the badge count used the raw unfiltered queue length. Now applies the same filament compatibility filter to the badge count.
 - **SpoolBuddy Daemon Can't Find Hardware Drivers** — The daemon's `nfc_reader.py` and `scale_reader.py` import `read_tag` and `scale_diag` as bare modules, but these files live in `spoolbuddy/scripts/` which isn't on Python's module search path. The systemd service sets `WorkingDirectory` to `spoolbuddy/` and runs `python -m daemon.main`, so only the `spoolbuddy/` and `daemon/` directories are on `sys.path`. Added `scripts/` to `sys.path` at daemon startup, resolved relative to the module file so it works regardless of install path. Also moved the `read_tag` import inside `NFCReader.__init__`'s try/except block — it was previously outside, so a missing module crashed the entire daemon instead of gracefully skipping NFC polling. Demoted hardware-not-available log messages from ERROR to INFO since missing modules are expected when hardware isn't connected.
-- **SpoolBuddy NFC Reader Silently Stops Detecting Tags** — The PN5180 NFC reader could drift into a stuck state where `activate_type_a()` silently returned `None` on every poll, indistinguishable from "no tag present". The daemon continued running with no errors logged (poll failures were at DEBUG level), making the problem invisible. The heartbeat also always reported `nfc_ok=True` regardless of actual reader health. The stuck state doesn't raise exceptions — the reader just returns `None` perpetually — so error-based recovery alone is insufficient. Added a preventive full hardware reset (RST pin toggle + RF re-init) every 60 seconds when idle, which is the same reset sequence that a service restart performs. Also added error-based auto-recovery (full hardware reset after 10 consecutive poll exceptions) for a different class of failure. Poll errors are now logged at WARNING level on first occurrence, and a periodic status line logs every 60 seconds showing poll count, error count, and state. The heartbeat now reports actual `nfc.ok` and `scale.ok` status from the reader instances instead of hardcoded `True`.
+- **SpoolBuddy NFC Reader Silently Stops Detecting Tags** — Two PN5180 NFC reader issues caused tags to stop being detected. First, after a successful `activate_type_a()` + SELECT, the card remained in ACTIVE state and would not respond to the next WUPA/REQA, causing every subsequent poll to return `None`. The tag appeared to be "removed" after ~1 second (3 consecutive misses) despite still being physically present, and was never re-detected. Added a brief RF field off/on cycle (13ms) before each poll to force all cards back to IDLE state. Second, the reader could drift into a deeper stuck state where `activate_type_a()` silently returned `None` perpetually without raising exceptions, indistinguishable from "no tag present" and invisible in logs (poll failures were at DEBUG level). Added a preventive full hardware reset (RST pin toggle + RF re-init) every 60 seconds when idle — the same reset a service restart performs. Also added error-based auto-recovery (full hardware reset after 10 consecutive poll exceptions) for exception-raising failures. Poll errors are now logged at WARNING level, a periodic status line logs every 60 seconds, and the heartbeat reports actual `nfc.ok` and `scale.ok` from the reader instances instead of hardcoded `True`.
 
 ### Improved
 - **SpoolBuddy Scale Value Stabilization** — The SpoolBuddy daemon now suppresses redundant scale weight reports: only sends updates when the weight changes by ≥2g. Previously every 1-second report interval sent a reading regardless of change, and stability state flips (stable ↔ unstable) also triggered reports — when ADC noise kept the spread hovering around the 2g stability threshold, the flag toggled every cycle, forcing a report with a slightly different weight each time. Removed stability flipping as a report trigger (the stable flag is still included in each report for consumers). Also increased the NAU7802 moving average window from 5 to 20 samples (500ms → 2s) to smooth ADC noise. The frontend also applies a 3g display threshold as defense-in-depth.

+ 12 - 0
spoolbuddy/daemon/nfc_reader.py

@@ -123,6 +123,18 @@ class NFCReader:
             except Exception as e:
                 logger.warning("Preventive NFC reset failed: %s", e)
 
+        # Brief RF field cycle before each poll to reset card state.
+        # After a successful SELECT, the card stays in ACTIVE state and won't
+        # respond to the next WUPA/REQA. Toggling RF forces all cards back to
+        # IDLE so they respond to the next activation attempt.
+        try:
+            self._nfc.rf_off()
+            time.sleep(0.003)
+            self._nfc.rf_on()
+            time.sleep(0.010)
+        except Exception:
+            pass  # Will be caught by activate_type_a() error handling below
+
         try:
             result = self._nfc.activate_type_a()
         except Exception as e: