Files
bambuddy/backend/app/models/spoolbuddy_device.py
T
maziggy aeca15b585 Add SpoolBuddy integration as optional filament management add-on
SpoolBuddy turns a Raspberry Pi 4B with a PN5180 NFC reader and
NAU7802 scale into a filament management station that integrates
with Bambuddy via REST API and WebSocket.

Backend: SpoolBuddyDevice model, 10 REST endpoints (/spoolbuddy/*),
6 WebSocket broadcast types, background offline-detection watchdog.

RPi daemon: asyncio service with concurrent NFC polling (300ms,
MIFARE Classic + Bambu HKDF key derivation), scale reading (10 SPS,
5-sample moving average, stability detection), and 10s heartbeat
with exponential backoff reconnect.

Frontend: kiosk-optimized 1024x600 UI at /spoolbuddy with Dashboard
(live weight + NFC spool detection), AMS Overview, Inventory,
Printers, and Settings pages. useSpoolBuddyState reducer hook
driven by WebSocket CustomEvents.

i18n: all 6 locales (en, de, fr, it, ja, pt-BR).
2026-02-22 15:27:54 +01:00

30 lines
1.4 KiB
Python

from datetime import datetime
from sqlalchemy import Boolean, DateTime, Float, Integer, String, func
from sqlalchemy.orm import Mapped, mapped_column
from backend.app.core.database import Base
class SpoolBuddyDevice(Base):
"""SpoolBuddy device registration for RPi-based filament management stations."""
__tablename__ = "spoolbuddy_devices"
id: Mapped[int] = mapped_column(primary_key=True)
device_id: Mapped[str] = mapped_column(String(50), unique=True, index=True)
hostname: Mapped[str] = mapped_column(String(100))
ip_address: Mapped[str] = mapped_column(String(45))
firmware_version: Mapped[str | None] = mapped_column(String(20))
has_nfc: Mapped[bool] = mapped_column(Boolean, default=True)
has_scale: Mapped[bool] = mapped_column(Boolean, default=True)
tare_offset: Mapped[int] = mapped_column(Integer, default=0)
calibration_factor: Mapped[float] = mapped_column(Float, default=1.0)
last_seen: Mapped[datetime | None] = mapped_column(DateTime)
pending_command: Mapped[str | None] = mapped_column(String(50))
nfc_ok: Mapped[bool] = mapped_column(Boolean, default=False)
scale_ok: Mapped[bool] = mapped_column(Boolean, default=False)
uptime_s: Mapped[int] = mapped_column(Integer, default=0)
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now())