Spool page for NFC links, bridge address; vendor-first new spool form
CI / test (push) Successful in 2m29s
CI / image (push) Successful in 39s

- /s/<id> shows a spool: rest in Spoolman and CC2 Control, where it is,
  last booking, history, links to Spoolman and the tag generator.
- Setting "Adresse der Bridge"; the tag generator can put <address>/s/<id>
  on the tag, so an iPhone held to the roll opens that page.
- New spool: vendor and material chosen from Spoolman, the vendor's
  filaments offered, values taken from similar filaments, duplicates
  pointed out and never created twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014GcEk5tkfFSYD6NTF66NkC
This commit is contained in:
Jonas MenzelandClaude Opus 5.5 committed 2026-10-25 21:52:23 +01:00
1 parent b37cd64909
commit 64ea91d107
10 files changed
+304 -49

No files matched your search

+29 -1
View File
@@ -20,7 +20,7 @@ from fastapi.templating import Jinja2Templates
from . import materials, newspool, tagcodec
from .bridge import Bridge
from .sshsource import CanvasRecordReader, HostKeyMismatch, KeyStore, SSHError, fingerprint
from .spoolman import SpoolmanError, summary
from .spoolman import SpoolmanError, SpoolmanNotFound, summary
from .storage import SettingsStore
log = logging.getLogger("web")
@@ -89,6 +89,10 @@ def create_app(data_dir: Path | None = None, *, bridge: Bridge | None = None, st
def index(request: Request):
return page(request, "status.html")
@app.get("/s/{smid}", response_class=HTMLResponse)
def spool_page(request: Request, smid: int):
return page(request, "spool.html", spool_id=smid)
@app.get("/log", response_class=HTMLResponse)
def log_page(request: Request):
return page(request, "log.html")
@@ -276,6 +280,30 @@ def create_app(data_dir: Path | None = None, *, bridge: Bridge | None = None, st
out.sort(key=lambda x: x["id"])
return {"spools": out, "id_offset": s.id_offset, "max_id": tagcodec.MAX_WEIGHT - s.id_offset}
@app.get("/api/spool/{smid}")
def spool_info(smid: int):
s = settings.get()
client = bridge.spoolman_factory(s)
try:
sm = client.spool(smid)
except SpoolmanNotFound:
raise HTTPException(404, f"Spoolman-Spule {smid} gibt es nicht") from None
except SpoolmanError as e:
raise HTTPException(502, str(e)) from None
finally:
client.close()
info = summary(sm)
name = info["label"]
return {
"spool": info,
"filament_name": (sm.get("filament") or {}).get("name") or "",
"spoolman_url": f"{s.spoolman_url}/spool/show/{smid}",
**bridge.spool_whereabouts(smid),
"storage": s.location_storage,
"log": [e for e in bridge.log.recent(300) if name in e["msg"]][:8],
"dry_run": s.dry_run,
}
@app.get("/api/spoolman/catalog")
def spoolman_catalog():
client = bridge.spoolman_factory(settings.get())