diff --git a/CHANGELOG.md b/CHANGELOG.md index b832fec69..12511fb9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ All notable changes to Bambuddy will be documented in this file. - **SpoolBuddy Dashboard Redesign** — Redesigned the SpoolBuddy dashboard with a two-column layout: left column shows device connection status (scale and NFC with state-colored icons — green when device is online, gray when offline) and a compact printers list with live status indicators; right column shows the current spool card. Cards use a dashed border style for a cleaner look. The large weight display card was removed in favor of the inline scale reading in the device card. ### Fixed -- **SpoolBuddy Daemon Crashes When NFC Module Not Installed** — The `NFCReader` constructor imported `read_tag` and instantiated `PN5180()` outside the try/except block, so a missing `read_tag` module raised an uncaught `ModuleNotFoundError` that crashed the entire daemon via `asyncio.gather`. The scale reader already handled its missing module gracefully. Moved the import and instantiation inside the existing try/except so a missing NFC driver sets `ok=False` and the daemon logs "NFC reader not available" and continues running the scale and heartbeat loops. +- **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. ### Improved - **SpoolBuddy Scale Value Stabilization** — The SpoolBuddy daemon now suppresses redundant scale weight reports: only sends updates when the weight changes by ≥2g or the stability state flips (stable ↔ unstable). Previously every 1-second report interval sent a reading regardless of change, causing the dashboard weight display to bounce continuously. The frontend also applies a 3g display threshold as defense-in-depth. diff --git a/spoolbuddy/daemon/main.py b/spoolbuddy/daemon/main.py index cb0d804e4..cad741d5d 100644 --- a/spoolbuddy/daemon/main.py +++ b/spoolbuddy/daemon/main.py @@ -4,7 +4,12 @@ import asyncio import logging import socket +import sys import time +from pathlib import Path + +# Add scripts/ to sys.path so hardware drivers (read_tag, scale_diag) are importable +sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts")) from .api_client import APIClient from .config import Config diff --git a/spoolbuddy/daemon/nfc_reader.py b/spoolbuddy/daemon/nfc_reader.py index 1f062cfac..1a623da9f 100644 --- a/spoolbuddy/daemon/nfc_reader.py +++ b/spoolbuddy/daemon/nfc_reader.py @@ -36,7 +36,7 @@ class NFCReader: self._ok = True logger.info("NFC reader initialized") except Exception as e: - logger.error("NFC init failed: %s", e) + logger.info("NFC not available: %s", e) @property def ok(self) -> bool: diff --git a/spoolbuddy/daemon/scale_reader.py b/spoolbuddy/daemon/scale_reader.py index c0420df8a..9579f8f8f 100644 --- a/spoolbuddy/daemon/scale_reader.py +++ b/spoolbuddy/daemon/scale_reader.py @@ -27,7 +27,7 @@ class ScaleReader: self._ok = True logger.info("Scale initialized (tare=%d, cal=%.6f)", tare_offset, calibration_factor) except Exception as e: - logger.error("Scale init failed: %s", e) + logger.info("Scale not available: %s", e) @property def ok(self) -> bool: